perbedaan dalam rencana pelaksanaan pada server UAT dan PROD

39

Saya ingin mengerti mengapa akan ada perbedaan yang sangat besar dalam pelaksanaan permintaan yang sama pada UAT (berjalan dalam 3 detik) vs PROD (berjalan dalam 23 detik).

Baik UAT dan PROD memiliki data dan indeks yang tepat.

PERTANYAAN:

set statistics io on;
set statistics time on;

SELECT CONF_NO,
       'DE',
       'Duplicate Email Address ''' + RTRIM(EMAIL_ADDRESS) + ''' in Maintenance',
       CONF_TARGET_NO
FROM   CONF_TARGET ct
WHERE  CONF_NO = 161
       AND LEFT(INTERNET_USER_ID, 6) != 'ICONF-'
       AND ( ( REGISTRATION_TYPE = 'I'
               AND (SELECT COUNT(1)
                    FROM   PORTFOLIO
                    WHERE  EMAIL_ADDRESS = ct.EMAIL_ADDRESS
                           AND DEACTIVATED_YN = 'N') > 1 )
              OR ( REGISTRATION_TYPE = 'K'
                   AND (SELECT COUNT(1)
                        FROM   CAPITAL_MARKET
                        WHERE  EMAIL_ADDRESS = ct.EMAIL_ADDRESS
                               AND DEACTIVATED_YN = 'N') > 1 ) ) 

PADA UAT:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 11 ms, elapsed time = 11 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(3 row(s) affected)
Table 'Worktable'. Scan count 256, logical reads 1304616, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'PORTFOLIO'. Scan count 1, logical reads 84761, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CAPITAL_MARKET'. Scan count 256, logical reads 9472, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CONF_TARGET'. Scan count 1, logical reads 100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 2418 ms,  elapsed time = 2442 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

masukkan deskripsi gambar di sini

Pada PROD:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(3 row(s) affected)
Table 'PORTFOLIO'. Scan count 256, logical reads 21698816, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CAPITAL_MARKET'. Scan count 256, logical reads 9472, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CONF_TARGET'. Scan count 1, logical reads 100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 23937 ms,  elapsed time = 23935 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

masukkan deskripsi gambar di sini

Perhatikan bahwa pada PROD kueri menyarankan indeks yang hilang dan itu bermanfaat seperti yang telah saya uji, tetapi itu bukan titik diskusi.

Saya hanya ingin memahami bahwa: PADA UAT - mengapa sql server membuat tabel pekerja dan pada PROD tidak? Itu menciptakan spool tabel pada UAT dan bukan pada PROD. Juga, mengapa waktu eksekusi sangat berbeda pada UAT vs PROD?

Catatan :

Saya menjalankan sql server 2008 R2 RTM di kedua server (segera akan menambal dengan SP terbaru).

UAT: Memori maks 8GB. MaxDop, afinitas prosesor, dan utas pekerja maks adalah 0.

Logical to Physical Processor Map:
*-------  Physical Processor 0
-*------  Physical Processor 1
--*-----  Physical Processor 2
---*----  Physical Processor 3
----*---  Physical Processor 4
-----*--  Physical Processor 5
------*-  Physical Processor 6
-------*  Physical Processor 7

Logical Processor to Socket Map:
****----  Socket 0
----****  Socket 1

Logical Processor to NUMA Node Map:
********  NUMA Node 0

PROD: memori maks 60GB. MaxDop, afinitas prosesor, dan utas pekerja maks adalah 0.

Logical to Physical Processor Map:
**--------------  Physical Processor 0 (Hyperthreaded)
--**------------  Physical Processor 1 (Hyperthreaded)
----**----------  Physical Processor 2 (Hyperthreaded)
------**--------  Physical Processor 3 (Hyperthreaded)
--------**------  Physical Processor 4 (Hyperthreaded)
----------**----  Physical Processor 5 (Hyperthreaded)
------------**--  Physical Processor 6 (Hyperthreaded)
--------------**  Physical Processor 7 (Hyperthreaded)

Logical Processor to Socket Map:
********--------  Socket 0
--------********  Socket 1

Logical Processor to NUMA Node Map:
********--------  NUMA Node 0
--------********  NUMA Node 1

PEMBARUAN:

XML Rencana Eksekusi UAT:

http://pastebin.com/z0PWvw8m

XML Rencana Eksekusi PROD:

http://pastebin.com/GWTY16YY

XML Rencana Eksekusi UAT - dengan Plan dihasilkan dari PROD:

http://pastebin.com/74u3Ntr0

Konfigurasi Server:

PROD: PowerEdge R720xd - Intel (R) Xeon (R) CPU E5-2637 v2 @ 3.50GHz.

UAT: PowerEdge 2950 - Intel (R) Xeon (R) CPU X5460 @ 3.16GHz

Saya telah memposting di answer.sqlperformance.com


PEMBARUAN:

Terima kasih kepada @swasheck untuk saran

Mengubah memori maks pada PROD dari 60GB ke 7680 MB, saya dapat menghasilkan paket yang sama di PROD. Kueri selesai bersamaan dengan UAT.

Sekarang saya perlu mengerti - MENGAPA? Juga, dengan ini, saya tidak akan bisa membenarkan server monster ini untuk mengganti server lama!

Kin Shah
sumber

Jawaban:

43

Ukuran potensial kumpulan penyangga memengaruhi pemilihan paket oleh pengoptimal kueri dalam beberapa cara. Sejauh yang saya tahu, hyper-threading tidak memengaruhi pilihan paket (meskipun jumlah penjadwal yang mungkin tersedia tentu saja bisa).

Memori ruang kerja

Untuk paket yang berisi iterator yang memakan memori seperti sortir dan hash, ukuran kumpulan buffer (antara lain) menentukan jumlah maksimum memori yang mungkin tersedia untuk kueri saat runtime.

Di SQL Server 2012 (semua versi) nomor ini dilaporkan pada simpul akar dari rencana kueri, di Optimizer Hardware Dependenciesbagian, ditampilkan sebagai Estimated Available Memory Grant. Versi sebelum 2012 tidak melaporkan angka ini dalam rencana acara.

Perkiraan hibah memori yang tersedia adalah input ke model biaya yang digunakan oleh optimizer kueri. Akibatnya, rencana alternatif yang membutuhkan operasi sortasi besar atau hashing lebih cenderung dipilih pada mesin dengan pengaturan kolam penyangga yang besar daripada pada mesin dengan pengaturan yang lebih rendah. Untuk instalasi dengan jumlah memori yang sangat besar, model biaya dapat berjalan terlalu jauh dengan pemikiran seperti ini - memilih paket dengan jenis atau hash yang sangat besar di mana strategi alternatif lebih disukai ( KB2413549 - Menggunakan memori dalam jumlah besar dapat menghasilkan rencana tidak efisien dalam SQL Server - TF2335 ).

Hibah memori ruang kerja bukan merupakan faktor dalam kasus Anda, tetapi itu adalah sesuatu yang perlu diketahui.

Akses data

Ukuran potensial dari buffer pool juga mempengaruhi model biaya pengoptimal untuk akses data. Salah satu asumsi yang dibuat dalam model adalah bahwa setiap permintaan dimulai dengan cache dingin - sehingga akses pertama ke halaman diasumsikan menimbulkan I / O fisik. Model tidak mencoba untuk memperhitungkan kemungkinan bahwa akses berulang akan datang dari cache, faktor yang tergantung pada ukuran potensial dari buffer pool antara lain.

Indeks Clustered Memindai dalam rencana kueri yang ditunjukkan dalam pertanyaan adalah salah satu contoh akses berulang; pindaian digulung ulang (diulangi, tanpa perubahan parameter berkorelasi) untuk setiap iterasi dari loop semi bergabung. Input terluar ke perkiraan semi join 28,7874 baris, dan properti rencana kueri untuk pemindaian ini menunjukkan perkiraan mundur di 27,7874 sebagai hasilnya.

Sekali lagi, dalam SQL Server 2012 saja, root iterator dari paket menunjukkan jumlah Estimated Pages Cacheddi Optimizer Hardware Dependenciesbagian tersebut. Angka ini melaporkan salah satu input ke algoritma penetapan biaya yang terlihat memperhitungkan kemungkinan akses halaman berulang yang berasal dari cache.

Efeknya adalah bahwa instalasi dengan ukuran kumpulan buffer maksimum yang lebih tinggi akan cenderung mengurangi biaya pemindaian (atau pencarian) yang membaca halaman yang sama lebih dari sekali lebih dari instalasi dengan ukuran buffer pool maksimum yang lebih kecil.

Dalam rencana sederhana, pengurangan biaya pada pemindaian ulang dapat dilihat dengan membandingkan (estimated number of executions) * (estimated CPU + estimated I/O)dengan perkiraan biaya operator, yang akan lebih rendah. Perhitungannya lebih kompleks dalam contoh rencana karena efek dari semi bergabung dan gabungan.

Namun demikian, rencana dalam pertanyaan tersebut tampaknya menunjukkan kasus di mana pilihan antara mengulang scan dan membuat indeks sementara cukup seimbang. Pada mesin dengan kumpulan buffer yang lebih besar, mengulangi pemindaian biayanya sedikit lebih rendah daripada membuat indeks. Pada mesin dengan kumpulan buffer yang lebih kecil, biaya pemindaian dikurangi dengan jumlah yang lebih kecil, yang berarti paket spool indeks terlihat sedikit lebih murah untuk pengoptimal.

Pilihan Rencana

Model biaya pengoptimal membuat sejumlah asumsi, dan berisi sejumlah besar perhitungan terperinci. Tidak selalu (atau bahkan biasanya) mungkin untuk mengikuti semua detail karena tidak semua angka yang kita perlukan terpapar, dan algoritme dapat berubah di antara rilis. Secara khusus, rumus penskalaan yang diterapkan untuk memperhitungkan peluang menemukan laman cache tidak diketahui dengan baik.

Lebih tepatnya pada kasus khusus ini, pilihan rencana pengoptimal didasarkan pada angka yang salah. Perkiraan jumlah baris dari Clustered Index Seek adalah 28,7874, sedangkan 256 baris ditemui pada saat runtime - hampir merupakan urutan besarnya. Kita tidak dapat secara langsung melihat informasi yang dimiliki pengoptimal tentang distribusi nilai yang diharapkan di dalam 28,7874 baris itu, tetapi sangat mungkin juga sangat salah.

Ketika perkiraan ini salah, pemilihan paket dan kinerja runtime pada dasarnya tidak lebih baik dari kebetulan. Rencana dengan spool indeks terjadi untuk melakukan lebih baik daripada mengulangi pemindaian, tetapi cukup salah untuk berpikir bahwa meningkatkan ukuran kolam penyangga adalah penyebab anomali.

Di mana pengoptimal memiliki informasi yang benar, kemungkinannya jauh lebih baik bahwa itu akan menghasilkan rencana eksekusi yang layak. Sebuah instance dengan memori lebih banyak umumnya akan berkinerja lebih baik pada beban kerja daripada instance lain dengan memori lebih sedikit, tetapi tidak ada jaminan, terutama ketika pemilihan paket didasarkan pada data yang salah.

Kedua contoh menyarankan indeks yang hilang dengan cara mereka sendiri. Satu melaporkan indeks hilang yang eksplisit, dan yang lainnya menggunakan spool indeks dengan karakteristik yang sama. Jika indeks memberikan kinerja yang baik dan stabilitas rencana, itu mungkin cukup. Kecenderungan saya adalah menulis ulang kueri juga, tapi itu mungkin cerita lain.

Paul White mengatakan GoFundMonica
sumber
18

Paul White telah menjelaskan dengan sangat jelas alasan di balik perilaku server - sql ketika berjalan di server dengan lebih banyak memori.

Juga, terima kasih banyak kepada @swasheck untuk pertama kali mengetahui masalah ini.

Membuka kasing dengan microsoft dan di bawah ini adalah apa yang disarankan.

Masalahnya diatasi dengan menggunakan jejak bendera T2335 sebagai parameter startup.

The KB2413549 - Menggunakan sejumlah besar memori dapat menghasilkan rencana efisien dalam SQL Server menjelaskan secara lebih detail.

Bendera jejak ini akan menyebabkan SQL Server menghasilkan rencana yang lebih konservatif dalam hal konsumsi memori saat menjalankan kueri. Itu tidak membatasi berapa banyak memori yang dapat digunakan SQL Server. Memori yang dikonfigurasi untuk SQL Server masih akan digunakan oleh cache data, eksekusi permintaan, dan konsumen lainnya. Harap pastikan bahwa Anda menguji opsi ini secara menyeluruh, sebelum mengubahnya menjadi lingkungan produksi.

Kin Shah
sumber
13

Pengaturan memori maksimum dan hipertensi dapat mempengaruhi pilihan paket.

Selain itu, saya perhatikan opsi "set" Anda berbeda di setiap lingkungan:

StatementSetOptions pada UAT:

ANSI_NULLS="true" 
ANSI_PADDING="true" 
ANSI_WARNINGS="true" 
ARITHABORT="true" 
CONCAT_NULL_YIELDS_NULL="true" 
NUMERIC_ROUNDABORT="false" 
QUOTED_IDENTIFIER="true" 

StatementSetOptions on Prod:

ANSI_NULLS="true" 
ANSI_PADDING="true" 
ANSI_WARNINGS="true" 
ARITHABORT="false" 
CONCAT_NULL_YIELDS_NULL="true"
NUMERIC_ROUNDABORT="false"
QUOTED_IDENTIFIER="true" 

SQL dapat menghasilkan rencana yang berbeda berdasarkan opsi SET. Ini sering terjadi jika Anda menangkap rencana dari sesi SSMS yang berbeda, atau dari eksekusi yang berbeda dari aplikasi.

Pastikan pengembang menggunakan string koneksi yang konsisten.

rottengeek
sumber
2
Anda benar dalam menyatakan bahwa Max Memory dan Hyperthreading dapat memengaruhi cache rencana, tetapi saya ingin tahu secara detail tentang apa dan mengapa ini terjadi. Hargai jawaban Anda.
Kin Shah
2
Seperti yang dikatakan Amanda, jika opsi SET berbeda dalam ARITHABORT, mungkin Anda harus melihat di dba.stackexchange.com/questions/9840/…
ARA