Saya punya tabel seperti ini:
CREATE TABLE Updates
(
UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
ObjectId INT NOT NULL
)
Pada dasarnya pelacakan pembaruan ke objek dengan ID yang meningkat.
Konsumen tabel ini akan memilih sepotong 100 objek ID yang berbeda, dipesan oleh UpdateId
dan mulai dari yang spesifik UpdateId
. Pada dasarnya, catat di mana ia tinggalkan dan kemudian minta pembaruan.
Saya menemukan ini sebagai masalah optimisasi yang menarik karena saya hanya dapat menghasilkan rencana kueri yang optimal dengan menulis kueri yang kebetulan melakukan apa yang saya inginkan karena indeks, tetapi tidak menjamin apa yang saya inginkan:
SELECT DISTINCT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
Dimana @fromUpdateId
parameter prosedur tersimpan.
Dengan rencana:
SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek
Karena pencarian pada UpdateId
indeks yang digunakan, hasilnya sudah bagus dan dipesan dari ID pembaruan terendah ke tertinggi seperti yang saya inginkan. Dan ini menghasilkan rencana aliran yang berbeda , yang saya inginkan. Tapi pemesanan jelas bukan perilaku terjamin, jadi saya tidak ingin menggunakannya.
Trik ini juga menghasilkan rencana kueri yang sama (meskipun dengan TOP yang berlebihan):
WITH ids AS
(
SELECT ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
ORDER BY UpdateId OFFSET 0 ROWS
)
SELECT DISTINCT TOP 100 ObjectId FROM ids
Padahal, saya tidak yakin (dan curiga tidak) apakah ini benar-benar menjamin pemesanan.
Satu pertanyaan yang saya harap SQL Server akan cukup pintar untuk disederhanakan adalah ini, tetapi akhirnya menghasilkan rencana permintaan yang sangat buruk:
SELECT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
GROUP BY ObjectId
ORDER BY MIN(UpdateId)
Dengan rencana:
SELECT <- Top N Sort <- Hash Match aggregate (50,000+ rows touched) <- Index Seek
Saya mencoba menemukan cara untuk menghasilkan rencana optimal dengan pencarian indeks UpdateId
dan aliran yang berbeda untuk menghapus duplikat ObjectId
. Ada ide?
Sampel data jika Anda menginginkannya. Objek jarang akan memiliki lebih dari satu pembaruan, dan seharusnya hampir tidak pernah memiliki lebih dari satu pembaruan dalam satu set 100 baris, itulah sebabnya saya mencari alur yang berbeda , kecuali ada sesuatu yang lebih baik yang tidak saya ketahui? Namun, tidak ada jaminan bahwa satu ObjectId
tidak akan memiliki lebih dari 100 baris dalam tabel. Tabel ini memiliki lebih dari 1.000.000 baris dan diperkirakan akan tumbuh dengan cepat.
Asumsikan pengguna ini memiliki cara lain untuk menemukan yang sesuai selanjutnya @fromUpdateId
. Tidak perlu mengembalikannya dalam permintaan ini.
sumber