Mengapa petunjuk READPAST menyebabkan tampilan indeks diabaikan?

10

Saya sedang menyelidiki menggunakan READPASTpetunjuk untuk mengurangi penguncian sumber daya dalam subsistem keuangan aplikasi kita.

Sepertinya cara yang baik untuk pergi karena catatan transaksi keuangan hanya pernah ditambahkan, tidak pernah diperbarui atau dihapus. Satu-satunya baris yang akan dilewati adalah baris baru yang dimasukkan dalam suatu transaksi; mereka secara efektif tidak ada di dunia luar sampai transaksi dilakukan.

Namun, saya melihat kinerja yang lebih buruk pada kueri yang memanfaatkan tampilan indeks yang telah saya berikan READPASTpetunjuknya. Membandingkan rencana kueri, sepertinya dengan petunjuk itu, pengoptimal kueri memilih untuk tidak menggunakan tampilan yang diindeks dan sebaliknya kembali memperlakukannya seperti tampilan biasa.

Saya tidak yakin mengapa itu terjadi; Saya membayangkan tampilan yang diindeks menjadi seperti indeks lain dalam kunci yang dapat dikunci selama operasi dan menambahkan READPASTakan bekerja sama.

SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa WITH (READPAST)
WHERE isa.TotalOwedAmount = 0.0

masukkan deskripsi gambar di sini

SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa
WHERE isa.TotalOwedAmount = 0.0

masukkan deskripsi gambar di sini

Menambahkan NOEXPANDpetunjuk juga tampaknya berhasil, tetapi saya tertarik untuk mempelajari lebih lanjut tentang mengapa READPASTpengoptimal kueri membuat pilihan itu sejak awal (sebagai bagian dari jawaban lengkap).

Mars
sumber

Jawaban:

7

Menggunakan kembali tabel contoh dan tampilan yang diindeks dari artikel saya Alasan Lain untuk Menggunakan NOEXPANDpetunjuk di Edisi Perusahaan :

CREATE TABLE dbo.T
(
    col1 integer NOT NULL
);
GO
INSERT dbo.T WITH (TABLOCKX)
    (col1)
SELECT 
    SV.number
FROM master.dbo.spt_values AS SV
WHERE 
    SV.type = N'P';
GO
CREATE VIEW dbo.VT
WITH SCHEMABINDING
AS
SELECT T.col1 
FROM dbo.T AS T;

Repro

Kueri ini cocok dengan tampilan yang diindeks (meskipun dengan agregat redundan):

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT;

Tampilan berindeks cocok

Menambahkan READPASThasil petunjuk dalam mengakses tabel dasar:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST);

Tampilan yang diindeks tidak cocok

Penjelasan

The READPASTpetunjuk adalah semantik-mempengaruhi. Pengoptimal menolak menulis ulang kueri sehingga hasilnya berubah. Menggambarkan:

Permintaan berikut dijalankan tanpa masalah:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST);

Namun:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST)
OPTION 
    (TABLE HINT (VT, FORCESCAN));

Menghasilkan kesalahan:

Msg 8722, Lantai 16, Negara Bagian 1, Jalur 42
Tidak dapat menjalankan kueri.
Semantic yang mempengaruhi petunjuk 'readpast' muncul di klausa 'WITH' objek 'VT'
tetapi tidak dalam klausa 'TABLE HINT' yang sesuai.
Ubah klausa OPTION (TABLE HINTS ...) sehingga semantic mempengaruhi petunjuk
cocok dengan klausa DENGAN.

Saat Anda mereferensikan tampilan yang diindeks tanpa NOEXPANDpetunjuk, tampilan diperluas (sebelum kompilasi dan optimisasi dimulai) untuk merujuk objek yang mendasarinya. Kemudian dalam proses, pengoptimal dapat mempertimbangkan mencocokkan pohon permintaan kembali ke tampilan yang diindeks, secara keseluruhan atau sebagian.

Ketika READPASTdigunakan tanpa NOEXPAND, petunjuk menyebar ke tabel dasar, mencegah pencocokan tampilan (semantik berbeda).

Dengan NOEXPAND, petunjuk itu berlaku untuk tampilan secara langsung, sehingga tidak ada masalah.

Paul White 9
sumber