Dalam SQL Server, Bagaimana Paralelisme Mengubah Hibah Memori?

9

Saya telah mendengar hal-hal yang bertentangan tentang hibah memori untuk kueri pemilihan paralel:

  • Hibah memori dikalikan dengan DOP
  • Hibah memori dibagi dengan DOP

Yang mana itu?

Erik Darling
sumber

Jawaban:

10

Sup?

Untuk permintaan SQL Server yang membutuhkan memori tambahan, hibah diturunkan untuk paket serial. Jika rencana paralel dieksplorasi dan dipilih, memori akan dibagi secara merata di antara utas.

Estimasi hibah memori didasarkan pada:

  • Jumlah baris (kardinalitas)
  • Ukuran baris (ukuran data)
  • Jumlah operator yang mengonsumsi memori secara bersamaan

Jika rencana paralel dipilih, ada beberapa overhead memori untuk memproses pertukaran paralel (mendistribusikan, mendistribusikan, dan mengumpulkan stream), namun kebutuhan memori mereka masih belum dihitung dengan cara yang sama.

Operator Pengonsumsi Memori

Operator yang paling umum yang meminta memori adalah

  • Macam-macam
  • Hash (bergabung, agregat)
  • Dioptimalkan Nested Loops

Operator yang kurang umum yang membutuhkan memori dimasukkan ke indeks penyimpanan kolom. Ini juga berbeda bahwa hibah memori saat ini dikalikan dengan DOP untuk mereka.

Kebutuhan memori untuk Macam biasanya jauh lebih tinggi daripada untuk hash. Urusan akan meminta setidaknya estimasi ukuran data untuk hibah memori, karena mereka perlu mengurutkan semua kolom hasil menurut elemen pemesanan. Hash membutuhkan memori untuk membangun tabel hash, yang tidak termasuk semua kolom yang dipilih.

Contohnya

Jika saya menjalankan kueri ini, dengan sengaja mengisyaratkan ke DOP 1, ia akan meminta memori 166 MB.

SELECT *
FROM 
     (  
        SELECT TOP (1000) 
               u.Id 
        FROM dbo.Users AS u
        ORDER BY u.Reputation
     ) AS u
OPTION(MAXDOP 1);

GILA

Jika saya menjalankan kueri ini (sekali lagi, DOP 1), paket akan berubah, dan hibah memori akan naik sedikit.

SELECT *
FROM (  
        SELECT TOP (1000) 
               u.Id
        FROM dbo.Users AS u
        ORDER BY u.Reputation
     ) AS u
JOIN (
        SELECT TOP (1000) 
               u.Id
        FROM dbo.Users AS u
        ORDER BY u.Reputation
     ) AS u2
ON u.Id = u2.Id
OPTION(MAXDOP 1);

GILA

Ada dua Urusan, dan sekarang Hash Bergabung. Memori hibah naik sedikit untuk mengakomodasi hash build, tetapi tidak berlipat ganda karena operator Sortir tidak dapat berjalan secara bersamaan.

Jika saya mengubah kueri untuk memaksa loop bersarang bergabung, hibah akan berlipat ganda untuk berurusan dengan Urusan bersamaan.

SELECT *
FROM (  
        SELECT TOP (1000) 
               u.Id
        FROM dbo.Users AS u
        ORDER BY u.Reputation
     ) AS u
INNER LOOP JOIN ( --Force the loop join
        SELECT TOP (1000) 
               u.Id
        FROM dbo.Users AS u
        ORDER BY u.Reputation
     ) AS u2
ON u.Id = u2.Id
OPTION(MAXDOP 1);

GILA

Memori hibah berlipat ganda karena Nested Loop bukan operator pemblokiran, dan Hash Join adalah.

Ukuran Data Penting

Kueri ini memilih data string kombinasi yang berbeda. Bergantung pada kolom mana yang saya pilih, ukuran hibah memori akan naik.

Ukuran cara data dihitung untuk data string variabel adalah baris * 50% dari panjang kolom yang dinyatakan. Ini berlaku untuk VARCHAR dan NVARCHAR, meskipun kolom NVARCHAR digandakan karena mereka menyimpan karakter byte ganda. Ini memang berubah dalam beberapa kasus dengan CE baru, tetapi detailnya tidak didokumentasikan.

Ukuran data juga penting untuk operasi hash, tetapi tidak pada tingkat yang sama dengan yang dilakukannya untuk Macam.

SELECT *
FROM 
     (  
        SELECT TOP (1000) 
                 u.Id          -- 166MB (INT)
               , u.DisplayName -- 300MB (NVARCHAR 40)
               , u.WebsiteUrl  -- 900MB (NVARCHAR 200)
               , u.Location    -- 1.2GB (NVARCHAR 100)
               , u.AboutMe     -- 9GB   (NVARCHAR MAX)
        FROM dbo.Users AS u
        ORDER BY u.Reputation
     ) AS u
OPTION(MAXDOP 1);

Tapi Bagaimana dengan Paralelisme?

Jika saya menjalankan kueri ini di DOP yang berbeda, hibah memori tidak dikalikan dengan DOP.

SELECT *
FROM (  
        SELECT TOP (1000) 
               u.Id
        FROM dbo.Users AS u
        ORDER BY u.Reputation
     ) AS u
INNER HASH JOIN (
        SELECT TOP (1000) 
               u.Id
        FROM dbo.Users AS u
        ORDER BY u.Reputation
     ) AS u2
ON u.Id = u2.Id
ORDER BY u.Id, u2.Id -- Add an ORDER BY
OPTION(MAXDOP ?);

GILA

Ada sedikit peningkatan untuk menangani buffer paralel lebih banyak per operator pertukaran, dan mungkin ada alasan internal bahwa Sort dan Hash build membutuhkan memori ekstra untuk menangani DOP yang lebih tinggi, tetapi jelas bukan faktor pengali.

Erik Darling
sumber