Bagaimana SQL Server menangani data untuk kueri di mana tidak ada cukup ruang di buffer cache?

10

Pertanyaan saya adalah bagaimana SQL Server menangani kueri yang perlu menarik lebih banyak volume data ke dalam buffer cache daripada ada ruang yang tersedia? Kueri ini akan berisi beberapa gabungan, jadi set hasil tidak ada dalam format ini sudah ada di disk, dan itu perlu mengkompilasi hasil. Tetapi bahkan setelah kompilasi, masih membutuhkan lebih banyak ruang daripada yang tersedia di cache buffer.

Saya akan memberi contoh. Misalkan Anda memiliki contoh SQL Server yang memiliki total ruang Buffer Cache 6GB tersedia. Saya menjalankan kueri dengan beberapa gabungan yang membaca data 7GB, bagaimana SQL Server dapat menanggapi permintaan ini? Apakah itu menyimpan sementara data di tempdb? Apakah itu gagal? Apakah ia melakukan sesuatu yang hanya membaca data dari disk dan mengkompilasi segmen sekaligus?

Selain itu, apa yang terjadi jika saya mencoba mengembalikan 7GB total data, apakah itu mengubah cara SQL Server menanganinya?

Saya sudah mengetahui beberapa cara untuk mengatasi ini, saya hanya ingin tahu bagaimana SQL Server menangani permintaan ini secara internal ketika dijalankan seperti yang dinyatakan.

Juga, saya yakin informasi ini ada di suatu tempat, tetapi saya tidak berhasil menemukannya.

Dustin
sumber
1
Dalam istilah awam, SQL Server akan menyimpan tabel kerja dan hasil pemrosesan internalnya sendiri di tempdb. Halaman dibaca dari disk saat dibutuhkan. Halaman akan tetap dalam memori sampai mereka dipaksa keluar, atau ketika SQL siap untuk mengkomitnya ke disk. Ini adalah ketika Anda menjalankan tempdb permintaan besar akan tumbuh. Saya telah melihat pertanyaan membuat sistem bertekuk lutut karena tempdb diizinkan untuk tumbuh tidak terkendali dan menghabiskan semua ruang yang tersisa di drive. Saya tahu ini tidak 100% akurat, hanya mencoba menjelaskannya dengan sederhana. Bagian yang menggunakan data bukanlah bagian yang mengelola lokasi data itu
datagod

Jawaban:

13

Halaman dibaca ke dalam memori sesuai kebutuhan, jika tidak ada memori bebas yang tersedia, halaman tertua yang tidak dimodifikasi diganti dengan halaman yang masuk.

Ini berarti jika Anda menjalankan kueri yang membutuhkan lebih banyak data daripada yang dapat ditampung dalam memori, banyak halaman akan hidup sangat singkat di memori, menghasilkan banyak I / O.

Anda dapat melihat efek ini dengan melihat penghitung "Page Life Expectancy" di Windows Performance Monitor. Lihatlah https://sqlperformance.com/2014/10/sql-performance/knee-jerk-page-life-expectancy untuk beberapa detail hebat tentang penghitung itu.

Dalam komentar, Anda bertanya secara spesifik apa yang terjadi ketika hasil kueri lebih besar dari ruang buffer yang tersedia. Ambil contoh paling sederhana, select * from some_very_big_table;- anggap tabelnya 32GB, dan max server memory (MB)dikonfigurasi pada 24GB. Semua 32GB data tabel akan dibaca ke dalam halaman di buffer halaman satu per satu, terkunci, diformat ke dalam paket jaringan, dan dikirim melintasi kawat. Ini terjadi halaman demi halaman; Anda bisa menjalankan 300 permintaan seperti itu pada saat yang sama, dan dengan asumsi tidak ada pemblokiran yang terjadi, data untuk setiap permintaan akan dibaca ke dalam ruang penyangga halaman, satu halaman pada satu waktu, dan dimasukkan ke dalam kawat secepat yang dapat dilakukan klien meminta dan mengkonsumsi data. Setelah semua data dari setiap halaman dikirim ke kabel, halaman menjadi tidak terkunci, dan akan segera diganti oleh beberapa halaman lain dari disk.

Dalam kasus kueri yang lebih kompleks, misalnya untuk agregat hasil dari beberapa tabel, halaman akan ditarik ke memori persis seperti di atas seperti yang diminta oleh prosesor kueri. Jika pemroses kueri membutuhkan ruang kerja sementara untuk menghitung hasil, ia akan tahu bahwa dimuka saat ia menyusun rencana untuk kueri, dan akan meminta ruang kerja (memori) dari SQLOS . SQLOS akan di beberapa titik (dengan asumsi itu tidak time out ), memberikan memori itu ke prosesor permintaan, di mana pemrosesan permintaan titik akan dilanjutkan. Jika pemroses kueri membuat kesalahan dalam memperkirakan berapa banyak memori yang diminta dari SQLOS, mungkin perlu melakukan "tumpahan ke disk"operasi, di mana data sementara ditulis ke tempdb dalam bentuk peralihan. Halaman-halaman yang telah ditulis ke tempdb akan tidak terkunci setelah mereka ditulis ke tempdb untuk memberikan ruang bagi halaman-halaman lain untuk dibaca ke dalam memori. Akhirnya proses permintaan akan kembali ke data yang disimpan di tempdb, paging yang menggunakan kait, ke halaman di buffer yang ditandai bebas.

Saya pasti melewatkan banyak detail yang sangat teknis dalam ringkasan di atas, tapi saya pikir itu menangkap esensi dari bagaimana SQL Server dapat memproses lebih banyak data daripada yang dapat ditampung dalam memori.

Max Vernon
sumber
Karena penasaran, pertanyaan apa yang menarik 7GB data? Saya harap ini adalah proses batch.
datagod
Mungkin tidak banyak dan Anda benar semoga akan menjadi proses batch. Saya hanya ingin tahu bagaimana SQL akan menangani permintaan itu
Dustin
5

Saya tidak dapat berbicara dengan apa yang sebenarnya akan dilakukan permintaan Anda dalam skenario ini tetapi SQL Server memiliki beberapa opsi tergantung pada seberapa banyak yang dibutuhkan.

  • Data dapat "tumpah" ke TempDB, ini akan menggunakan disk Anda
  • Halaman lama dapat didorong keluar dari cache buffer Anda
  • SQL Server dapat memuat beberapa halaman ke buffer cache, menggunakannya, kemudian memutar halaman baru

Cara terbaik untuk mengetahui apa yang akan terjadi adalah dengan membuat skenario di lingkungan pengembang dan mencari tahu.

Arthur D
sumber
2

Pertanyaan saya adalah bagaimana SQL Server menangani kueri yang perlu menarik lebih banyak volume data ke dalam buffer cache kemudian ada ruang yang tersedia

Untuk menjawab bagian spesifik ini izinkan saya memberi tahu Anda bagaimana ini dikelola. Halaman berukuran 8KB. Ketika Anda menjalankan kueri yang meminta kumpulan data besar dan yang membutuhkan banyak halaman untuk dibawa ke memori SQL Server tidak akan membawa semua halaman sekaligus. Ini akan menemukan halaman tertentu dan membawa satu per satu halaman 8KB ke dalam memori, membaca data dari sana dan memberi Anda hasilnya dan ini akan berlangsung sekarang seandainya ia menghadapi situasi di mana memori kurang dalam hal itu halaman lama akan disiram ke disk seperti @Max tunjukkan. Seperti yang Anda tebak dengan benar, memori rendah ini dapat memperlambat segalanya karena beberapa waktu akan dihabiskan untuk menghapus halaman lama. Di sinilah pos pemeriksaan dan Lazywritermuncul dalam gambar. Lazywriter adalah milik mereka untuk memastikan memori bebas selalu ada untuk membawa halaman baru ke disk. Ketika buffer gratis rendah ditemukan, ia dipicu dan menciptakan ruang kosong untuk menjadi halaman baru.

EDIT

Saya mengerti, tetapi bagian yang sedikit membingungkan saya adalah apa yang terjadi jika Anda bergabung dengan \ filtering data dan hasilnya melebihi ukuran cache.

Memori untuk bergabung dan memfilter diputuskan bahkan sebelum kueri berjalan dan anggap benar-benar ada kehancuran memori dan memori yang diperlukan untuk menjalankan operasi tidak tersedia. Prosesor SQL Server akan memberikan "memori yang diperlukan" yang merupakan

Memori yang diperlukan: Memori minimum yang diperlukan untuk menjalankan sort and hash join. Ini disebut wajib karena permintaan tidak akan mulai tanpa memori ini tersedia. SQL server menggunakan memori ini untuk membuat struktur data internal untuk menangani sort dan hash join.

Jadi setidaknya permintaan akan mulai berjalan tetapi selama runtime itu sangat mungkin hasil menengah tumpah ke Tempdb membuatnya lambat. Saya sangat menyarankan Anda membaca Understanding Query Memory Grant

Shanky
sumber
Saya mengerti, tetapi bagian yang sedikit membingungkan saya adalah apa yang terjadi jika Anda bergabung dengan \ filtering data dan hasilnya melebihi ukuran cache. Data perlu dikompilasi untuk menghasilkan set kembali, tetapi set kembali lebih besar dari ukuran cache. Apakah secara internal masih siklus halaman melalui cache sampai menghasilkan hasil akhir? Pemikiran saya adalah bahwa ia akan menulis hasilnya ke tempdb karena melebihi cache dan kemudian membaca dari disk itu, tetapi tidak tahu apakah itu yang terjadi
Dustin
2
@Dustin Diedit jawaban saya, silakan periksa
Shanky