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.
Jawaban:
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, danmax 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.
sumber
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.
Cara terbaik untuk mengetahui apa yang akan terjadi adalah dengan membuat skenario di lingkungan pengembang dan mencari tahu.
sumber
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
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
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
sumber