Operator menggunakan tempdb untuk menumpahkan data selama eksekusi dengan tingkat tumpahan 2

16

Saya berjuang untuk meminimalkan biaya operasi pengurutan pada rencana permintaan dengan peringatan Operator usedtempdbto spill data during execution with spill level 2

Saya telah menemukan beberapa tulisan yang berhubungan dengan data tumpahan selama eksekusi dengan tingkat tumpahan 1 , tetapi bukan tingkat 2. Tingkat 1 tampaknya disebabkan oleh statistik yang usang , bagaimana dengan tingkat 2? Saya tidak dapat menemukan apa pun yang terkait dengan level 2.

Saya menemukan artikel ini sangat menarik terkait dengan Urutkan peringatan:

Jangan pernah abaikan peringatan pengurutan di SQL Server

Server Sql Saya?

Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64) Jun 17 2016 19:14:09 Hak cipta (c) Microsoft Corporation Enterprise Edition (64-bit) pada Windows NT 6.3 (Build 9600:) (Hypervisor)

Perangkat Keras Saya?

menjalankan kueri di bawah ini untuk menemukan harware:

- Informasi perangkat keras dari SQL Server 2012

SELECT cpu_count AS [Logical CPU Count], hyperthread_ratio AS [Hyperthread Ratio],
cpu_count/hyperthread_ratio AS [Physical CPU Count], 
physical_memory_kb/1024 AS [Physical Memory (MB)], affinity_type_desc, 
virtual_machine_type_desc, sqlserver_start_time
FROM sys.dm_os_sys_info WITH (NOLOCK) OPTION (RECOMPILE);

masukkan deskripsi gambar di sini

memori yang dialokasikan saat ini

SELECT
(physical_memory_in_use_kb/1024) AS Memory_usedby_Sqlserver_MB,
(locked_page_allocations_kb/1024) AS Locked_pages_used_Sqlserver_MB,
(total_virtual_address_space_kb/1024) AS Total_VAS_in_MB,
process_physical_memory_low,
process_virtual_memory_low
FROM sys.dm_os_process_memory;

masukkan deskripsi gambar di sini

ketika saya menjalankan query saya dengan cakupan satu tahun, saya tidak mendapatkan peringatan apa pun, seperti gambar di bawah ini:

masukkan deskripsi gambar di sini

Tetapi ketika saya menjalankannya hanya untuk lingkup 1 hari saya mendapatkan peringatan ini on the sort operator:

masukkan deskripsi gambar di sini

ini pertanyaannya:

    DECLARE @FromDate SMALLDATETIME = '19-OCT-2016 11:00'
    DECLARE @ToDate   SMALLDATETIME = '20-OCT-2016 12:00'




    SELECT      DISTINCT
                a.strAccountCode ,
                a.strAddressLine6 ,
                a.strPostalCode ,
                CASE    WHEN a.strCountryCode IN ('91','92') THEN 'GB-Int'
                        ELSE a.strCountryCode
                        END AS [strCountryCode]
    FROM        Bocss2.dbo.tblBAccountParticipant AS ap
    INNER JOIN  Bocss2.dbo.tblBAccountParticipantAddress AS apa ON ap.lngParticipantID = apa.lngParticipantID
                                                                AND apa.sintAddressTypeID = 2
    INNER JOIN  Bocss2.dbo.tblBAccountHolder AS ah ON ap.lngParticipantID = ah.lngParticipantID
    INNER JOIN  Bocss2.dbo.tblBAddress AS a ON apa.lngAddressID = a.lngAddressID
                                            AND a.blnIsCurrent = 1
    INNER JOIN  Bocss2.dbo.tblBOrder AS o ON ap.lngParticipantID = o.lngAccountParticipantID
                                        AND o.sdtmOrdCreated >= @FromDate
                                        AND o.sdtmOrdCreated < @ToDate

OPTION(RECOMPILE)

rencana kueri ada di sini

rencana permintaan menggunakan pastetheplan

Pertanyaan: 1) dalam paket permintaan saya melihat ini:

StatementOptmEarlyAbortReason="GoodEnoughPlanFound" CardinalityEstimationModelVersion="70" 

mengapa 70? Saya menggunakan server sql 2014

2) bagaimana cara saya menyingkirkan operator semacam itu (jika memungkinkan)?

3) Saya telah melihat harapan hidup halaman cukup rendah, selain menambahkan lebih banyak memori ke server ini, apakah ada hal lain yang bisa saya lihat untuk melihat apakah saya dapat mencegah peringatan ini?

Bersulang

Pembaruan setelah jawaban dari Shanky dan Paul White

Saya telah memeriksa statistik saya sesuai dengan skrip di bawah ini, dan tampaknya semuanya benar dan diperbarui.

ini semua indeks dan tabel yang digunakan dalam kueri ini.

DBCC SHOW_STATISTICS ('dbo.tblBAddress','IDXF_tblBAddress_lngAddressID__INC')
GO
DBCC SHOW_STATISTICS  ('dbo.tblBOrder','IX_tblBOrder_sdtmOrdCreated_INCL')
GO
DBCC SHOW_STATISTICS ('dbo.tblBAccountHolder','PK_tblAccountHolder')
GO
DBCC SHOW_STATISTICS ('dbo.tblBAccountParticipant','PK_tblBAccountParticipants')
GO
DBCC SHOW_STATISTICS ('dbo.tblBAccountParticipantAddress','IDXF_tblBAccountParticipantAddress_lngParticipantID')
GO

inilah yang telah saya kembalikan:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Ini adalah hasil parsial, tetapi saya telah mengunjungi kembali semuanya.

Untuk pembaruan statistik saat ini saya memiliki Ola Hallengren

Indeks Mengoptimalkan Pekerjaan - dijadwalkan berjalan seminggu sekali - Minggu

EXECUTE [dbo].[IndexOptimize] 
@Databases = 'USER_DATABASES,-%Archive', 
@Indexes = 'ALL_INDEXES' , 
@FragmentationLow = NULL,
@FragmentationMedium = NULL,
@FragmentationHigh = NULL,
@PageCountLevel=1000,
@StatisticsSample =100
,@UpdateStatistics = 'Index', 
@OnlyModifiedStatistics = 'Y',
@TimeLimit=10800, 
@LogToTable = 'Y'

Meskipun statistik tampaknya diperbarui Setelah saya menjalankan skrip berikut, saya tidak mendapat peringatan lagi pada operator sortir.

UPDATE STATISTICS [Bocss2].[dbo].[tblBOrder]  WITH FULLSCAN
--1 hour  04 min 14 sec

UPDATE STATISTICS [Bocss2].[dbo].tblBAddress  WITH FULLSCAN
-- 45 min 29 sec

UPDATE STATISTICS  [Bocss2].[dbo].tblBAccountHolder WITH FULLSCAN
-- 26 SEC

UPDATE STATISTICS  [Bocss2].[dbo].tblBAccountParticipant WITH FULLSCAN
-- 4 min

UPDATE STATISTICS  [Bocss2].[dbo].tblBAccountParticipantAddress WITH FULLSCAN
-- 7 min 3 sec
Marcello Miorelli
sumber
Berapa waktu permintaan dikurangi?
influen
Saya tidak pernah bisa mengimplementasikan solusi yang memungkinkan saya untuk menjaga statistik diperbarui pada tabel sebesar itu. Solusinya adalah dengan mempartisi tabel dan menggunakan statistik incrementao, tetapi saya tidak pernah turun untuk mengimplementasikannya karena saya meninggalkan perusahaan itu. Sesuatu yang ingin saya terapkan.
Marcello Miorelli

Jawaban:

17

bagaimana dengan level 2? Saya tidak dapat menemukan apa pun yang terkait dengan level 2.

Sesuai Dokumen MS Lama ini , angka dalam tumpahan Tempdb menandakan berapa banyak pass yang diperlukan untuk data untuk mengurutkan data. Jadi Tumpahan 1 berarti harus melewati 1 kali untuk mengurutkan data dan 2 berarti harus melewati 2 kali.

Mengutip dari blog:

Jika kueri yang melibatkan operasi pengurutan menghasilkan kelas peristiwa Sort Peringatan dengan nilai level tumpahan 2, kinerja kueri dapat dipengaruhi karena beberapa lintasan melewati data diperlukan untuk mengurutkan data. Dalam contoh di bawah ini kita melihat nilai level tumpahan 1, yang berarti bahwa satu kali melewati data sudah cukup untuk menyelesaikan pengurutan.

mengapa 70? Saya menggunakan server sql 2014

Ini karena tingkat kompatibilitas basis data dalam gambar BUKAN 120 (yang menandakan tingkat kompatibilitas basis data 2014) karena bukan 120 permintaan akan diproses menggunakan model estimasi kardinalitas lama (CE) yang disebut sebagai CardinalityEstimationModelVersion="70". Saya yakin Anda sadar bahwa dari SQL Server 2014 kami memiliki CE baru.

bagaimana cara saya menyingkirkan operator semacam itu (jika memungkinkan)?

Perintah berbeda yang Anda gunakan menyebabkan operasi pengurutan. Data yang sedang disortir tidak masuk ke dalam memori sehingga tumpah ke tempdb dan ketika ini terjadi semacam pengurutan dengan tanda seru kuning diberikan dalam rencana eksekusi. Menyortir peringatan tidak selalu menjadi masalah.

Anda dapat melihat dalam rencana eksekusi bahwa perkiraan jumlah baris yang akan disortir adalah 1, tetapi 16.353 ditemui pada saat run time. Jumlah memori yang dicadangkan untuk pengurutan didasarkan pada ukuran input yang diperkirakan (diperkirakan), dan tidak dapat tumbuh selama eksekusi (dalam kasus ini).

Hibah memori kecil untuk kueri (1632KB) juga dibagikan di antara operator yang mengkonsumsi memori secara bersamaan (sort dan loop bergabung 'dioptimalkan' ). Dalam paket Anda, itu berarti 33,33% (544KB) tersedia untuk pengurutan saat membaca baris (fraksi memori input). Ini tidak cukup memori untuk mengurutkan 16.353 baris, sehingga tumpah ke tempdb . Tumpahan tingkat tunggal tidak cukup untuk menyelesaikan penyortiran, sehingga tingkat tumpahan kedua diperlukan (lihat referensi di bagian akhir untuk detail lebih lanjut tentang tingkat tumpahan).

Sortir properti

Sortir properti seperti yang terlihat di SQL Sentry Plan Explorer

Memperbarui statistik kemungkinan akan membantu masalah estimasi kardinalitas. Anda mungkin mengalami masalah kunci naik, terutama di atas meja tblBOrder. Pilihan sederhana dari tabel itu dengan tanggal literal dari pertanyaan Anda kemungkinan akan memperkirakan satu baris sekarang.

Saya telah melihat harapan hidup halaman cukup rendah, selain menambahkan lebih banyak memori ke server ini, apakah ada hal lain yang bisa saya lihat untuk melihat apakah saya dapat mencegah peringatan ini?

PLE adalah indikasi jumlah aktivitas I / O, apakah sudah meningkat? Begitu juga ini sering terjadi atau hanya ketika Anda menjalankan kueri tertentu atau ini baru terjadi hari ini. Hindari reaksi spontan, pertama-tama kita perlu memastikan bahwa Anda benar-benar menghadapi tekanan memori atau permintaan jahat yang menghasilkan terlalu banyak I / O yang menyebabkan hal ini. Bagaimanapun Anda sudah memiliki memori 97 G yang ditetapkan untuk SQL Server.

Untuk informasi lebih lanjut tentang level tumpahan dan masalah kunci naik, lihat:

Shanky
sumber