Kinerja SQL Server lebih lambat setelah mengalokasikan lebih banyak CPU dan RAM

33

Kami memiliki SQL Server 2008 R2 (10.50.1600) yang berjalan di server virtual Windows 2008 R2. Setelah memutakhirkan CPU dari 1 inti ke 4 dan RAM dari 4 gb ke 10 gb, kami perhatikan kinerjanya lebih buruk.

Beberapa pengamatan yang saya lihat:

  1. Kueri yang membutuhkan waktu <5 detik untuk dijalankan sekarang membutuhkan waktu> 200 detik.
  2. CPU dipatok pada 100 dengan sqlservr.exe sebagai biang keladinya.
  3. Hitungan pilih (*) pada tabel dengan 4,6 juta baris membutuhkan waktu lebih dari 90 detik.
  4. Proses yang berjalan di server belum berubah. Satu-satunya perubahan adalah meningkatkan cpu dan ram.
  5. Sql server lain memiliki file paging statis di mana server ini diatur untuk mengelolanya sendiri.

Adakah yang pernah mengalami masalah ini sebelumnya?

Per sp_BlitzErik, saya berlari

EXEC dbo.sp_BlitzFirst @SinceStartup = 1;

Memberi saya hasil ini.

tunggu statistik

Jeff
sumber
9
Terakhir kali saya melihat pertanyaan serupa pada SE, itu karena seseorang menghidupkan VM CPU dan RAM tetapi host VM tidak benar-benar memiliki banyak CPU dan banyak RAM . Jadi saya akan periksa dulu.
user253751

Jawaban:

55

Ada banyak hal yang terjadi di sini, dan sebagian besar sangat luas dan tidak jelas.

  1. 2008R2 RTM keluar pada 21 April 2010. Ini benar-benar di luar dukungan. Anda akan ingin memprioritaskan mendapatkan Paket Layanan terbaru, yang keluar sekitar 3 tahun yang lalu. Dengan begitu Anda akan dilindungi jika Anda menabrak bug aneh atau sesuatu. Buka di sini untuk mencari tahu apa yang perlu Anda unduh.

  2. Karena Anda menambahkan vCPU (dari 1 ke 4) dan tidak mengubah pengaturan apa pun, kueri Anda sekarang dapat berjalan paralel. Saya tahu ini terdengar seperti mereka semua akan lebih cepat, tapi tunggu dulu!

  3. Anda mungkin telah menambahkan RAM, tetapi Anda mungkin belum mengubah Memori Server Maks sehingga server Anda dapat memanfaatkannya.

  4. Cari tahu apa yang menunggu server Anda. Proyek open source yang saya kerjakan menyediakan skrip gratis untuk membantu Anda mengukur SQL Server Anda. Kepala di sini jika Anda ingin mencoba mereka.

Anda akan ingin mengambil sp_BlitzFirst untuk memeriksa statistik tunggu server Anda. Anda dapat menjalankannya dengan beberapa cara.

Ini akan menunjukkan kepada Anda apa yang server Anda sudah tunggu sejak dimulai.

EXEC dbo.sp_BlitzFirst @SinceStartup = 1;

Ini akan menunjukkan kepada Anda pertanyaan apa yang sedang menunggu sekarang, selama jendela 30 detik.

EXEC dbo.sp_BlitzFirst @Seconds = 30, @ExpertMode = 1;

Setelah Anda mengetahui pertanyaan apa yang menunggu (ada banyak hal yang ditulis tentang statistik menunggu di luar sana), Anda dapat mulai membuat perubahan untuk mengendalikan keadaan.

Jika Anda melihat mereka menunggu CXPACKET, itu berarti pertanyaan Anda berjalan paralel, dan mungkin saling menginjak. Jika Anda menekan ini, Anda mungkin ingin mempertimbangkan untuk menabrak Ambang Batas Biaya untuk Paralelisme hingga 50, dan mungkin menurunkan MAXDOP menjadi 2.

Setelah langkah ini adalah ketika Anda ingin menggunakan sesuatu seperti sp_WhoIsActive atau sp_BlitzWho (yang terakhir ada di repo GitHub dari sebelumnya) untuk mulai mengambil rencana kueri. Selain dari statistik menunggu, mereka adalah salah satu hal paling penting yang dapat Anda lihat untuk mencari tahu apa yang salah.

Anda mungkin juga ingin memeriksa artikel ini oleh Jonathan Kehayias tentang Penghitung VMWare untuk memeriksa sehubungan dengan SQL Server.

Memperbarui

Meninjau statistik tunggu dan bocah itu aneh. Pasti ada sesuatu dengan CPU. Server Anda kebanyakan duduk bosan, tetapi ketika segalanya memanas, segalanya menjadi buruk. Saya akan mencoba memecah ini dengan mudah.

  1. Anda memukul menunggu racun disebut THREADPOOL. Anda tidak memiliki banyak, tetapi itu masuk akal karena server Anda tidak terlalu aktif. Saya akan menjelaskan mengapa sebentar lagi.

  2. Anda memiliki rata-rata lama menunggu SOS_SCHEDULER_YIELDdan CXPACKET. Anda menggunakan VM, jadi Anda ingin memastikan bahwa SQL Server memiliki reservasi, atau bahwa kotak itu tidak terlalu langganan. Tetangga yang berisik benar-benar dapat merusak hari Anda di sini. Anda juga akan ingin memastikan bahwa server / VM guest / VM host tidak berjalan dalam mode Balanced Power. Ini membuat CPU Anda berputar ke kecepatan rendah yang tidak perlu, dan mereka tidak segera kembali ke kecepatan penuh.

  3. Bagaimana mereka mengikat? Dengan 4 CPU Anda memiliki 512 utas pekerja. Perlu diingat, Anda memiliki jumlah yang sama dengan satu CPU, tetapi sekarang setelah kueri Anda bisa paralel, mereka dapat mengkonsumsi lebih banyak utas pekerja. Dalam kasus Anda 4 utas per cabang paralel dari permintaan paralel.

Apa yang terjadi paralel? Kemungkinan besar semuanya. Ambang Batas Biaya default untuk Paralelisme adalah 5. Angka itu dijadikan default pada akhir 90-an yang bekerja pada desktop yang terlihat seperti ini .

GILA

Memang, perangkat keras Anda lebih kecil dari kebanyakan laptop, tetapi Anda masih sedikit di depan hal itu.

Ketika banyak pertanyaan paralel berjalan, Anda kehabisan utas pekerja tersebut. Ketika itu terjadi, pertanyaan hanya duduk menunggu thread untuk pergi. Di situlah juga SOS_SCHEDULER_YIELDmasuk. Kueri sedang melangkah keluar dari CPU dan tidak kembali untuk waktu yang lama. Saya tidak melihat menunggu pemblokiran, jadi Anda kemungkinan besar hanya semua diisi pada paralelisme intra-query menunggu.

Apa yang bisa kau lakukan?

  1. Pastikan tidak ada dalam mode Daya Seimbang
  2. Ubah MAXDOP ke 2
  3. Ubah ambang biaya untuk paralelisme menjadi 50
  4. Ikuti artikel Jon K. di atas untuk memvalidasi kesehatan VM
  5. Gunakan skrip yang dipanggil sp_BlitzIndexuntuk mencari permintaan indeks yang hilang.

Untuk pemecahan masalah yang lebih menyeluruh, lihat whitepaper yang saya tulis untuk Google tentang ukuran perangkat keras di cloud.

Semoga ini membantu!

Erik Darling
sumber
8

Iya nih! Saya sudah mengalami situasi semacam ini pada SQL Server vms di server kami. Lihatlah waktu siap CPU tuan rumah vm dan penghitung driver balon memori. CPU SIAP WAKTU - BLOG BAGIAN I dan Memahami VMware Ballooning Bekerja dengan sysadmin saya adalah kuncinya, tetapi tidak mudah ...

thundercougarfalcon
sumber
5

Satu hal yang saya tidak tunjukkan menunjukkan, bahwa menambahkan vCPU ke VM sering dapat memperlambatnya karena penjadwalan.

Ide dasarnya adalah jika VM memiliki 4 vCPU, maka hypervisor harus menunggu hingga 4 core fisik tersedia sehingga dapat menjadwalkan semua vCPU, bahkan jika 3 dari mereka idle.

Jika Anda tidak memiliki banyak core di host Anda, dan beban kerja Anda yang lain sedang sibuk, ini dapat mengakibatkan menunggu ekstra, dan penurunan kinerja yang signifikan.

Dalam VMware ESXi Anda dapat melihatnya di grafik lanjutan melalui CPU Ready.

Inilah salah satu dari banyak artikel dengan contoh dunia nyata dari kejadian ini dan bagaimana ia didiagnosis .

Menambahkan lebih banyak RAM juga dapat menyebabkan penurunan kinerja tiba-tiba jika alokasi RAM VM lebih besar dari simpul NUMA.

Selain itu, konfigurasi vCPU Anda (vSockets vs. vCores) sebenarnya dapat memengaruhi beberapa aplikasi seperti SQL server. Ini karena SQL server itu sendiri sadar NUMA (untuk menghindari jenis penurunan kinerja spanning NUMA yang sama) dan karena VMware dapat menghadirkan node NUMA virtual secara berbeda.

Ini tercakup dalam posting blog di situs VMware sendiri .


Makhluk ini berkata, saya senang Anda menyelesaikan masalah dengan bantuan Erik, tetapi Anda mungkin ingin melihat dan mempertimbangkan hal-hal ini juga.

briantis
sumber
3

Hanya sedikit bantuan (tidak dapat memposting ini sebagai komentar) melanjutkan jawaban @ sp_BlitzErik, saya mendapat beberapa pertanyaan dengan Pinal dan Max Vernon (tidak dapat mengingat di mana) yang mengatakan berapa banyak MAXDOP yang harus Anda gunakan:

/*************************************************************************
Author          :   Kin Shah
Purpose         :   Recommend MaxDop settings for the server instance
Tested RDBMS    :   SQL Server 2008R2

**************************************************************************/
declare @hyperthreadingRatio bit
declare @logicalCPUs int
declare @HTEnabled int
declare @physicalCPU int
declare @SOCKET int
declare @logicalCPUPerNuma int
declare @NoOfNUMA int

select @logicalCPUs = cpu_count -- [Logical CPU Count]
    ,@hyperthreadingRatio = hyperthread_ratio --  [Hyperthread Ratio]
    ,@physicalCPU = cpu_count / hyperthread_ratio -- [Physical CPU Count]
    ,@HTEnabled = case 
        when cpu_count > hyperthread_ratio
            then 1
        else 0
        end -- HTEnabled
from sys.dm_os_sys_info
option (recompile);

select @logicalCPUPerNuma = COUNT(parent_node_id) -- [NumberOfLogicalProcessorsPerNuma]
from sys.dm_os_schedulers
where [status] = 'VISIBLE ONLINE'
    and parent_node_id < 64
group by parent_node_id
option (recompile);

select @NoOfNUMA = count(distinct parent_node_id)
from sys.dm_os_schedulers -- find NO OF NUMA Nodes 
where [status] = 'VISIBLE ONLINE'
    and parent_node_id < 64

-- Report the recommendations ....
select
    --- 8 or less processors and NO HT enabled
    case 
        when @logicalCPUs < 8
            and @HTEnabled = 0
            then 'MAXDOP setting should be : ' + CAST(@logicalCPUs as varchar(3))
                --- 8 or more processors and NO HT enabled
        when @logicalCPUs >= 8
            and @HTEnabled = 0
            then 'MAXDOP setting should be : 8'
                --- 8 or more processors and HT enabled and NO NUMA
        when @logicalCPUs >= 8
            and @HTEnabled = 1
            and @NoofNUMA = 1
            then 'MaxDop setting should be : ' + CAST(@logicalCPUPerNuma / @physicalCPU as varchar(3))
                --- 8 or more processors and HT enabled and NUMA
        when @logicalCPUs >= 8
            and @HTEnabled = 1
            and @NoofNUMA > 1
            then 'MaxDop setting should be : ' + CAST(@logicalCPUPerNuma / @physicalCPU as varchar(3))
        else ''
        end as Recommendations

-------------------------------------------------- -------

--MAX VERNON 

/* 
   This will recommend a MAXDOP setting appropriate for your machine's NUMA memory
   configuration.  You will need to evaluate this setting in a non-production 
   environment before moving it to production.

   MAXDOP can be configured using:  
   EXEC sp_configure 'max degree of parallelism',X;
   RECONFIGURE

   If this instance is hosting a Sharepoint database, you MUST specify MAXDOP=1 
   (URL wrapped for readability)
   http://blogs.msdn.com/b/rcormier/archive/2012/10/25/
   you-shall-configure-your-maxdop-when-using-sharepoint-2013.aspx

   Biztalk (all versions, including 2010): 
   MAXDOP = 1 is only required on the BizTalk Message Box
   database server(s), and must not be changed; all other servers hosting other 
   BizTalk Server databases may return this value to 0 if set.
   http://support.microsoft.com/kb/899000
*/
SET NOCOUNT ON;

DECLARE @CoreCount int;
SET @CoreCount = 0;
DECLARE @NumaNodes int;

/*  see if xp_cmdshell is enabled, so we can try to use 
    PowerShell to determine the real core count
*/
DECLARE @T TABLE (
    name varchar(255)
    , minimum int
    , maximum int
    , config_value int
    , run_value int
);
INSERT INTO @T 
EXEC sp_configure 'xp_cmdshell';
DECLARE @cmdshellEnabled BIT;
SET @cmdshellEnabled = 0;
SELECT @cmdshellEnabled = 1 
FROM @T
WHERE run_value = 1;
IF @cmdshellEnabled = 1
BEGIN
    CREATE TABLE #cmdshell
    (
        txt VARCHAR(255)
    );
    INSERT INTO #cmdshell (txt)
    EXEC xp_cmdshell 'powershell -OutputFormat Text -NoLogo -Command "& {Get-WmiObject -namespace "root\CIMV2" -class Win32_Processor -Property NumberOfCores} | select NumberOfCores"';
    SELECT @CoreCount = CONVERT(INT, LTRIM(RTRIM(txt)))
    FROM #cmdshell
    WHERE ISNUMERIC(LTRIM(RTRIM(txt)))=1;
    DROP TABLE #cmdshell;
END
IF @CoreCount = 0 
BEGIN
    /* 
        Could not use PowerShell to get the corecount, use SQL Server's 
        unreliable number.  For machines with hyperthreading enabled
        this number is (typically) twice the physical core count.
    */
    SET @CoreCount = (SELECT i.cpu_count from sys.dm_os_sys_info i); 
END

SET @NumaNodes = (
    SELECT MAX(c.memory_node_id) + 1 
    FROM sys.dm_os_memory_clerks c 
    WHERE memory_node_id < 64
    );

DECLARE @MaxDOP int;

/* 3/4 of Total Cores in Machine */
SET @MaxDOP = @CoreCount * 0.75; 

/* if @MaxDOP is greater than the per NUMA node
    Core Count, set @MaxDOP = per NUMA node core count
*/
IF @MaxDOP > (@CoreCount / @NumaNodes) 
    SET @MaxDOP = (@CoreCount / @NumaNodes) * 0.75;

/*
    Reduce @MaxDOP to an even number 
*/
SET @MaxDOP = @MaxDOP - (@MaxDOP % 2);

/* Cap MAXDOP at 8, according to Microsoft */
IF @MaxDOP > 8 SET @MaxDOP = 8;

PRINT 'Suggested MAXDOP = ' + CAST(@MaxDOP as varchar(max));
SQL pembalap
sumber
Script pertama mengembalikan hasil kosong. Yang kedua mengembalikan yang disarankan MAXDOP = 2yang sejalan dengan @sp_BlitzErik. Terima kasih!
Jeff