Katakanlah saya punya satu meja
CREATE TABLE Ticket (
TicketId int NOT NULL,
InsertDateTime datetime NOT NULL,
SiteId int NOT NULL,
StatusId tinyint NOT NULL,
AssignedId int NULL,
ReportedById int NOT NULL,
CategoryId int NULL
);
Dalam contoh ini TicketId
adalah Kunci Utama.
Saya ingin pengguna dapat membuat kueri "sebagian ad-hoc" terhadap tabel ini. Saya katakan sebagian karena beberapa bagian dari query akan selalu diperbaiki:
- Kueri akan selalu melakukan filter rentang pada
InsertDateTime
- Permintaan akan selalu
ORDER BY InsertDateTime DESC
- Permintaan akan hasil halaman
Pengguna dapat memfilter secara opsional pada salah satu kolom lainnya. Mereka dapat memfilter tanpa, satu, atau banyak. Dan untuk setiap kolom pengguna dapat memilih dari serangkaian nilai yang akan diterapkan sebagai disjungsi. Sebagai contoh:
SELECT
TicketId
FROM (
SELECT
TicketId,
ROW_NUMBER() OVER(ORDER BY InsertDateTime DESC) as RowNum
FROM Ticket
WHERE InsertDateTime >= '2013-01-01' AND InsertDateTime < '2013-02-01'
AND StatusId IN (1,2,3)
AND (CategoryId IN (10,11) OR CategoryId IS NULL)
) _
WHERE RowNum BETWEEN 1 AND 100;
Sekarang asumsikan tabel memiliki 100.000.000 baris.
Yang terbaik yang bisa saya dapatkan adalah indeks penutup yang mencakup masing-masing kolom "opsional":
CREATE NONCLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime DESC
) INCLUDE (
SiteId, StatusId, AssignedId, ReportedById, CategoryId
);
Ini memberi saya rencana permintaan sebagai berikut:
- PILIH
- Saring
- Teratas
- Proyek Urutan (Hitung Skalar)
- Segmen
- Indeks mencari
- Segmen
- Proyek Urutan (Hitung Skalar)
- Teratas
- Saring
Sepertinya cukup bagus. Sekitar 80% -90% dari biaya berasal dari operasi Index Seek, yang ideal.
Adakah strategi yang lebih baik untuk menerapkan pencarian semacam ini?
Saya tidak perlu ingin melepas pemfilteran opsional ke klien karena dalam beberapa kasus hasil yang ditetapkan dari bagian "tetap" bisa 100s atau 1000s. Klien kemudian juga akan bertanggung jawab untuk menyortir dan paging yang mungkin terlalu banyak bekerja untuk klien.
sumber
RowNum BETWEEN 101 AND 200
?Jawaban:
Jika beban kerja khusus ini adalah mayoritas kueri terhadap tabel, Anda dapat mempertimbangkan:
Pertimbangan:
Keuntungan:
sumber
Saya telah menggunakan teknik ini di masa lalu. Tabelnya tidak terlalu besar tetapi kriteria pencariannya lebih kompleks.
Ini adalah versi singkatnya.
sumber
Mengingat dua prasyarat pertama Anda, saya akan melihat indeks berkerumun di
InsertDateTime
.sumber
mengapa Anda tidak mempertimbangkan mempartisi? Ini tersedia di SQL 2008 ke atas tetapi membutuhkan edisi Perusahaan (atau edisi Pengembang).
Pada dasarnya, Anda membagi tabel Anda menjadi beberapa partisi dan Anda menentukan kriteria partisi Anda (fungsi) apakah Anda rentang tanggal?
https://www.simple-talk.com/sql/database-administration/gail-shaws-sql-server-howlers/
sumber
Jika klien memfilter dengan cara yang hampir sama berulang-ulang, Anda dapat membuat indeks untuk permintaan tersebut.
Misalnya klien memfilter pada SiteId dan StatusId Anda dapat membuat indeks tambahan:
Dengan cara ini, sebagian besar pertanyaan 'lebih umum' dapat berjalan cepat.
sumber