Skenario: SQL Server 2014 (v12.0.4100.1)
Layanan .NET menjalankan kueri ini:
SELECT name, base_object_name
FROM sys.synonyms
WHERE schema_id IN (SELECT schema_id
FROM sys.schemas
WHERE name = N'XXXX')
ORDER BY name
... yang mengembalikan sekitar 6500 baris tetapi sering kali keluar setelah 3+ menit. Di XXXX
atas bukan 'dbo'.
Jika saya menjalankan kueri ini dalam SSMS sebagai UserA, kueri kembali dalam waktu kurang dari satu detik.
Ketika dijalankan sebagai UserB (yang merupakan cara layanan .NET terhubung), kueri membutuhkan waktu 3-6 menit , dan memiliki% CPU sebesar 25% (dari 4 core) sepanjang waktu.
UserA adalah Login Domain dalam peran sysadmin.
UserB adalah SQL Login dengan:
EXEC sp_addrolemember N'db_datareader', N'UserB'
EXEC sp_addrolemember N'db_datawriter', N'UserB'
EXEC sp_addrolemember N'db_ddladmin', N'UserB'
GRANT EXECUTE TO [UserB]
GRANT CREATE SCHEMA TO [UserB]
GRANT VIEW DEFINITION TO [UserB]
Saya bisa menduplikasi ini dalam SSMS dengan membungkus SQL di atas dalam satu Execute as...Revert
blok, sehingga kode .NET keluar dari gambar.
Rencana eksekusi terlihat sama. Saya membuat XML dan hanya ada sedikit perbedaan (CompileTime, CompileCPU, CompileMemory).
Statistik IO semua tidak menunjukkan bacaan fisik:
Nilai tabel 'sysobjes'. Pindai hitungan 0, bacaan logis 19970, bacaan fisik 0, bacaan baca-depan 0, bacaan logis lob 0, bacaan fisik lob 0, bac baca baca depan 0. Tabel 'Workfile'. Pindai jumlah 0, bacaan logis 0, bacaan fisik 0, bacaan baca-depan 0, bacaan logis lob 0, bacaan fisik lob 0, bac baca baca-depan 0. Tabel 'Meja Kerja'. Pindai jumlah 0, bacaan logis 0, bacaan fisik 0, bacaan baca-depan 0, bacaan logis lob 0, bacaan fisik lob 0, bac baca baca-depan 0. Tabel 'sysschobjs'. Pindai hitungan 1, bacaan logis 9122, bacaan fisik 0, bacaan baca depan 0, bacaan logis lob 0, bacaan fisik lob 0, bacaan baca lob depan 0. Tabel 'sysclsobjs'. Pindai menghitung 0, bacaan logis 2, bacaan fisik 0, bacaan baca-depan 0, bacaan logis lob 0, bacaan fisik lob 0, bacaan baca lob depan 0.
Status menunggu XEvent (untuk permintaan ~ 3 menit) adalah:
+ --------------------- + ------------ + -------------- -------- + ------------------------------ + ---------- ------------------- + | Jenis Tunggu | Tunggu Hitungan | Total Waktu Tunggu (ms) | Total Waktu Tunggu Sumberdaya (ms) | Total Waktu Tunggu Sinyal (ms) | + --------------------- + ------------ + -------------- -------- + ------------------------------- + --------- -------------------- + | SOS_SCHEDULER_YIELD | 37300 | 427 | 20 | 407 | | NETWORK_IO | 5 | 26 | 26 | 0 | | IO_COMPLETION | 3 | 1 | 1 | 0 | + --------------------- + ------------ + -------------- -------- + ------------------------------- + --------- -------------------- +
Jika saya menulis ulang kueri (dalam SSMS, saya tidak memiliki akses ke Kode Aplikasi) ke
declare @id int
SELECT @id=schema_id FROM sys.schemas WHERE name = N'XXXX'
SELECT a.name, base_object_name FROM sys.synonyms a
WHERE schema_id = @id
ORDER BY name
kemudian UserB berjalan pada kecepatan (cepat) yang sama dengan UserA.
Jika saya menambahkan db_owner
ke UserB, maka, sekali lagi, kueri berjalan <1 detik.
Skema yang dibuat melalui templat ini:
DECLARE @TranName VARCHAR(20)
SELECT @TranName = 'MyTransaction'
BEGIN TRANSACTION @TranName
GO
IF NOT EXISTS (SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = '{1}')
BEGIN
EXEC('CREATE SCHEMA [{1}]')
EXEC sp_addextendedproperty @name='User', @value='{0}', @level0type=N'Schema', @level0name=N'{1}'
END
GO
{2}
COMMIT TRANSACTION MyTransaction;
GO
Dan {2} adalah, saya percaya, daftar Sinonim yang dibuat dalam skema itu.
Profil Permintaan pada dua titik ke dalam permintaan:
Saya sudah membuka tiket dengan Microsoft.
Kami juga mencoba menambahkan UserB ke db_owner
, dan kemudian mengambil DENY
semua hak istimewa yang kami ketahui terkait dengan db_owner
. Hasilnya adalah permintaan yang cepat. Entah kami melewatkan sesuatu (sepenuhnya mungkin), atau ada pemeriksaan khusus untuk db_owner
peran tersebut.
access check cache bucket count
danaccess check cache quota
opsi konfigurasi sebelumnya. Harus bermain-main dengan itu sedikit.WHILE(1=1) BEGIN DBCC FREESYSTEMCACHE ('TokenAndPermUserStore') WAITFOR DELAY '00:00:05' END
dalam satu lingkaran selamanya, kueri diselesaikan dalam waktu kurang dari 2 menit vs 8 menit.Jika ini masih hidup - kami memiliki masalah yang sama - tampaknya jika Anda adalah dbo atau sysadmin maka akses apa pun ke sys.objects (atau semacamnya) - maka itu instan tanpa pemeriksaan terhadap objek individual.
jika itu adalah db_datareader rendah maka ia harus memeriksa setiap objek pada gilirannya ... itu disembunyikan dalam rencana kueri karena ini berperilaku lebih seperti fungsi daripada tampilan / tabel
rencananya terlihat sama, tetapi melakukan hal yang berbeda di balik tenda
sumber
Menggunakan jejak flag 9481 tampaknya untuk mengatasi masalah ini bagi saya.
CE (Cardinality Estimator) pada 2014 (compat 120) berubah dari 2012 dan 2008, dan menggunakan pasukan TF 9481 menggunakan CE 2012.
Lihat Penaksir Kardinalitas SQL 2014 Makan TSQL Buruk untuk Sarapan oleh Kendra Little.
sumber