Permintaan SQL Server lambat saat paginasi

14

Saya melihat beberapa perilaku aneh dengan kueri T-SQL berikut di SQL Server 2012:

SELECT Id 
FROM dbo.Person 
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name

Melaksanakan kueri ini sendiri memberi saya sekitar 1.300 hasil dalam waktu kurang dari dua detik (ada indeks teks lengkap aktif Name)

Namun, ketika saya mengubah kueri untuk ini:

SELECT Id 
FROM dbo.Person 
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name
OFFSET 0 rows
FETCH NEXT 10 ROWS ONLY

Butuh lebih dari 20 detik untuk memberi saya 10 hasil.

Permintaan berikut bahkan lebih buruk:

SELECT Id 
FROM ( 
    SELECT ROW_NUMBER() OVER (ORDER BY Name) AS RowNum, Id 
    FROM dbo.Person
    WHERE CONTAINS(Name, '"John" AND "Smith"') ) AS RowConstrainedResult 
WHERE RowNum >= 0 AND RowNum < 11 
ORDER BY RowNum

Selesai lebih dari 1,5 menit!

Ada ide?

Rencana lambat

Lambat

Rencana cepat

Cepat

ay
sumber
Apa yang terjadi jika Anda mengubah kueri kedua ke SELECT TOP 10 * .... ORDER BY Name?
Lamak
Pada kolom apa indeks IX_PersonSearch ... dibuat? Anda mendapatkan pencarian kunci karena Anda memilih * dari tabel dan indeks yang digunakan tidak mengandung semua kolom output. Saya pikir Anda harus memilih hanya kolom yang Anda butuhkan dan kemudian memasukkannya ke dalam indeks non-clustered sebagai kolom yang disertakan, bukan kolom indeks.
Marcel N.
Bisakah Anda memposting indeks di atas meja (buat skrip)?
3
ID selalu disertakan dalam setiap indeks yang tidak tercakup. Ini adalah cara SQL Server dapat melakukan pencarian kunci (berdasarkan ID).
usr
1
Apa yang saya lupa sebutkan: Ketika saya melakukan permintaan yang sama dengan LIKE alih-alih berisi, juga cepat. (Dikotak-kotak atau tidak)

Jawaban:

7

Karena Anda hanya ingin nama yang TOP 10dipesan, menurutnya akan lebih cepat untuk mengerjakan indeks namedan melihat apakah setiap baris cocok dengan CONTAINS(Name, '"John" AND "Smith"') )predikat.

Mungkin dibutuhkan lebih banyak baris untuk menemukan 10 pertandingan yang diperlukan kemudian diharapkan dan masalah kardinalitas ini diperparah dengan jumlah pencarian kunci.

Sebuah hack cepat untuk menghentikannya menggunakan rencana ini akan mengubah ORDER BYke ORDER BY Name + ''meskipun menggunakan CONTAINSTABLEdalam hubungannya dengan FORCE ORDERjuga harus bekerja.

Martin Smith
sumber
3

Ini terlihat seperti misestimasi selektivitas klasik. Tidak yakin apa yang dapat dilakukan tentang itu sebagai "driver" dari kueri adalah pencarian teks lengkap yang Anda tidak dapat menambah dengan statistik.

Cobalah menulis ulang where containspredikat ke inner join containstable( CONTAINSTABLE ) dan terapkan petunjuk bergabung pesanan untuk memaksa bentuk rencana.

Itu bukan solusi yang sempurna karena memiliki masalah pemeliharaan, tetapi saya tidak bisa melihat cara lain.

usr
sumber
Terima kasih atas jawaban Anda, saya sudah mencobanya. Hasil yang sama: Ketika tidak menggunakan pagination, permintaannya sangat cepat. Ketika Paginating tiba-tiba menjadi sangat lambat lagi: /
Oke, bisakah Anda memposting paket sebagai gambar dan permintaan Anda? Dugaan saya bahwa kami belum berhasil menghasilkan bentuk yang diinginkan.
usr
3

Saya berhasil memecahkan masalah:

Seperti yang saya katakan dalam pertanyaan ada indikasi pada semua kolom + statistik untuk setiap kolom. (Karena pertanyaan SEPERTI warisan) Saya menghapus semua indeks dan statistik, menambahkan pencarian teks lengkap dan voa, permintaan menjadi sangat cepat.

Tampaknya indikasi mengarah ke Rencana Eksekusi yang berbeda.

Terima kasih banyak atas bantuannya!

ay
sumber
1
Menghapus indeks sepenuhnya adalah salah satu cara untuk mencegahnya agar tidak digunakan, saya rasa!
Martin Smith