Saya berjuang untuk meminimalkan biaya operasi pengurutan pada rencana permintaan dengan peringatan Operator used
tempdbto 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);
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;
ketika saya menjalankan query saya dengan cakupan satu tahun, saya tidak mendapatkan peringatan apa pun, seperti gambar di bawah ini:
Tetapi ketika saya menjalankannya hanya untuk lingkup 1 hari saya mendapatkan peringatan ini on the sort operator
:
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 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:
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
sumber
Jawaban:
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:
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.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 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.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:
sumber