Tambahan: SQL Server 2012 menunjukkan beberapa peningkatan kinerja di area ini tetapi tampaknya tidak mengatasi masalah khusus yang disebutkan di bawah ini. Ini tampaknya harus diperbaiki di versi utama berikutnya setelah
SQL Server 2012!
Rencana Anda menunjukkan bahwa sisipan tunggal menggunakan prosedur berparameter (mungkin diparameterisasi otomatis) sehingga waktu parse / kompilasi untuk ini harus diminimalkan.
Saya pikir saya akan melihat ini sedikit lebih banyak, jadi siapkan loop ( skrip ) dan coba sesuaikan jumlah VALUES
klausa dan catat waktu kompilasi.
Saya kemudian membagi waktu kompilasi dengan jumlah baris untuk mendapatkan waktu kompilasi rata-rata per klausa. Hasilnya di bawah ini
![Grafik](https://i.stack.imgur.com/PiJFm.png)
Hingga 250 VALUES
klausa yang ada, waktu kompilasi / jumlah klausa memiliki tren sedikit naik tetapi tidak terlalu dramatis.
![Grafik](https://i.stack.imgur.com/hZkeq.png)
Tapi kemudian terjadi perubahan mendadak.
Bagian data itu ditunjukkan di bawah ini.
+------+----------------+-------------+---------------+---------------+
| Rows | CachedPlanSize | CompileTime | CompileMemory | Duration/Rows |
+------+----------------+-------------+---------------+---------------+
| 245 | 528 | 41 | 2400 | 0.167346939 |
| 246 | 528 | 40 | 2416 | 0.162601626 |
| 247 | 528 | 38 | 2416 | 0.153846154 |
| 248 | 528 | 39 | 2432 | 0.157258065 |
| 249 | 528 | 39 | 2432 | 0.156626506 |
| 250 | 528 | 40 | 2448 | 0.16 |
| 251 | 400 | 273 | 3488 | 1.087649402 |
| 252 | 400 | 274 | 3496 | 1.087301587 |
| 253 | 400 | 282 | 3520 | 1.114624506 |
| 254 | 408 | 279 | 3544 | 1.098425197 |
| 255 | 408 | 290 | 3552 | 1.137254902 |
+------+----------------+-------------+---------------+---------------+
Ukuran rencana cache yang telah tumbuh secara linier tiba-tiba turun tetapi CompileTime meningkat 7 kali lipat dan CompileMemory meningkat. Ini adalah titik potong antara paket yang paketnya diparameterisasi otomatis (dengan 1.000 parameter) ke yang tidak diparameterisasi. Setelah itu tampaknya menjadi kurang efisien secara linier (dalam hal jumlah klausul nilai yang diproses dalam waktu tertentu).
Tidak yakin mengapa ini harus terjadi. Agaknya ketika menyusun rencana untuk nilai literal tertentu, ia harus melakukan beberapa aktivitas yang tidak berskala linier (seperti pengurutan).
Tampaknya tidak memengaruhi ukuran rencana kueri yang di-cache ketika saya mencoba kueri yang seluruhnya terdiri dari baris duplikat dan tidak memengaruhi urutan output tabel konstanta (dan saat Anda memasukkan ke dalam tumpukan waktu yang dihabiskan untuk menyortir akan menjadi sia-sia bahkan jika itu terjadi).
Selain itu, jika indeks berkerumun ditambahkan ke tabel, rencana tersebut masih menunjukkan langkah pengurutan eksplisit sehingga tampaknya tidak menyortir pada waktu kompilasi untuk menghindari pengurutan pada waktu proses.
![Rencana](https://i.stack.imgur.com/6FFYo.jpg)
Saya mencoba melihat ini di debugger tetapi simbol publik untuk versi SQL Server 2008 saya tampaknya tidak tersedia, jadi saya harus melihat UNION ALL
konstruksi yang setara di SQL Server 2005.
Jejak tumpukan tipikal ada di bawah
sqlservr.exe!FastDBCSToUnicode() + 0xac bytes
sqlservr.exe!nls_sqlhilo() + 0x35 bytes
sqlservr.exe!CXVariant::CmpCompareStr() + 0x2b bytes
sqlservr.exe!CXVariantPerformCompare<167,167>::Compare() + 0x18 bytes
sqlservr.exe!CXVariant::CmpCompare() + 0x11f67d bytes
sqlservr.exe!CConstraintItvl::PcnstrItvlUnion() + 0xe2 bytes
sqlservr.exe!CConstraintProp::PcnstrUnion() + 0x35e bytes
sqlservr.exe!CLogOp_BaseSetOp::PcnstrDerive() + 0x11a bytes
sqlservr.exe!CLogOpArg::PcnstrDeriveHandler() + 0x18f bytes
sqlservr.exe!CLogOpArg::DeriveGroupProperties() + 0xa9 bytes
sqlservr.exe!COpArg::DeriveNormalizedGroupProperties() + 0x40 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x18a bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!CQuery::PqoBuild() + 0x3cb bytes
sqlservr.exe!CStmtQuery::InitQuery() + 0x167 bytes
sqlservr.exe!CStmtDML::InitNormal() + 0xf0 bytes
sqlservr.exe!CStmtDML::Init() + 0x1b bytes
sqlservr.exe!CCompPlan::FCompileStep() + 0x176 bytes
sqlservr.exe!CSQLSource::FCompile() + 0x741 bytes
sqlservr.exe!CSQLSource::FCompWrapper() + 0x922be bytes
sqlservr.exe!CSQLSource::Transform() + 0x120431 bytes
sqlservr.exe!CSQLSource::Compile() + 0x2ff bytes
Jadi menghapus nama di pelacakan tumpukan tampaknya menghabiskan banyak waktu untuk membandingkan string.
Artikel KB ini menunjukkan yang DeriveNormalizedGroupProperties
terkait dengan apa yang dulu disebut tahap normalisasi pemrosesan kueri
Tahap ini sekarang disebut mengikat atau algebrizing dan mengambil keluaran pohon parse ekspresi dari tahap penguraian sebelumnya dan keluaran pohon ekspresi algebrized (pohon prosesor kueri) untuk maju ke pengoptimalan (pengoptimalan rencana trivial dalam kasus ini) [ref] .
Saya mencoba satu eksperimen lagi ( Script ) yang akan menjalankan ulang pengujian asli tetapi melihat tiga kasus berbeda.
- String Nama Depan dan Nama Belakang dengan panjang 10 karakter tanpa duplikat.
- String Nama Depan dan Nama Belakang dengan panjang 50 karakter tanpa duplikat.
- String Nama Depan dan Nama Belakang dengan panjang 10 karakter dengan semua duplikat.
![Grafik](https://i.stack.imgur.com/YhmSO.png)
Dapat dilihat dengan jelas bahwa semakin panjang string semakin buruk hal-hal dan sebaliknya semakin banyak duplikat semakin baik hal-hal. Seperti yang disebutkan sebelumnya, duplikat tidak memengaruhi ukuran rencana yang di-cache, jadi saya berasumsi bahwa harus ada proses identifikasi duplikat saat membangun pohon ekspresi algebrized itu sendiri.
Edit
Satu tempat di mana informasi ini dimanfaatkan ditunjukkan oleh @Lieven di sini
SELECT *
FROM (VALUES ('Lieven1', 1),
('Lieven2', 2),
('Lieven3', 3))Test (name, ID)
ORDER BY name, 1/ (ID - ID)
Karena pada waktu kompilasi dapat menentukan bahwa Name
kolom tidak memiliki duplikat, pengurutannya dilewati oleh 1/ (ID - ID)
ekspresi sekunder pada waktu proses (pengurutan dalam rencana hanya memiliki satu ORDER BY
kolom) dan tidak ada kesalahan bagi dengan nol yang dimunculkan. Jika duplikat ditambahkan ke tabel maka operator pengurutan memperlihatkan dua urutan menurut kolom dan kesalahan yang diharapkan dimunculkan.