Як SQL Server обробляє дані для запиту, коли в буферному кеші недостатньо місця?


10

Моє запитання полягає в тому, як SQL Server обробляє запит, який потребує залучення більшої кількості даних у кеш-пам'ять, ніж є місця? Цей запит містив би декілька приєднань, тому набір результатів не існує в такому форматі вже на диску, і йому потрібно буде зібрати результати. Але навіть після компіляції все одно потрібно більше місця, ніж доступно в кеш-пам'яті.

Наведу приклад. Припустимо, у вас є екземпляр SQL Server, який має 6 ГБ пам’яті буферного кешу. Я запускаю запит з декількома приєднаннями, який читає 7 ГБ даних, як SQL Server здатний відповісти на цей запит? Чи тимчасово він зберігає дані в tempdb? Невдача? Чи робить це щось, що просто зчитує дані з диска і збирає сегменти за один раз?

Крім того, що станеться, якщо я намагаюся повернути 7 ГБ загальних даних, чи зміниться це спосіб обробки SQL Server?

Мені вже відомо кілька способів вирішення цього питання, мені просто цікаво, як SQL Server обробляє цей запит внутрішньо, коли він працює, як зазначено.

Крім того, я впевнений, що ця інформація десь є, але я її невдало знайшов.


1
Зрозуміло, просто SQL Server буде зберігати робочі таблиці та результати власної внутрішньої обробки у tempdb. Сторінки читаються з диска при необхідності. Сторінки залишатимуться в пам’яті до тих пір, поки вони не будуть витіснені або коли SQL буде готовий зафіксувати їх на диску. Це коли ви запускаєте великий запит tempdb буде рости. Я бачив, як запити ставлять систему на коліна, тому що tempdb було дозволено безперешкодно рости і витрачало весь залишок місця на диску. Я знаю, що це не на 100% точно, просто намагаюся пояснити це просто. Частина, яка використовує дані, не є тією частиною, яка керує розташуванням цих даних
datagod

Відповіді:


13

Сторінки читаються в пам'ять за потребою, якщо вільної пам'яті немає, найстаріша немодифікована сторінка замінюється на вхідну сторінку.

Це означає, що якщо ви виконаєте запит, який вимагає більше даних, ніж вміщається в пам'яті, багато сторінок проживуть в пам'яті дуже короткий термін, в результаті чого багато вводу-виводу.

Ви можете побачити цей ефект, переглянувши лічильник "Тривалість життя сторінки" в Моніторі роботи Windows. Подивіться на https://sqlperformance.com/2014/10/sql-performance/knee-jerk-page-life-expectancy, щоб ознайомитись із чудовими деталями про цей лічильник.

У коментарях ви запитували конкретно, що відбувається, коли результати запиту більше, ніж наявне буферне місце. Візьмемо найпростіший приклад, select * from some_very_big_table;- припустимо, що стіл становить 32 ГБ і max server memory (MB)налаштований на 24 ГБ . Усі 32 Гб даних таблиці будуть читатись на сторінках у буфері сторінок одна за одною, зачепленими, відформатований у мережеві пакети та надісланий по всій мережі. Це відбувається окремо за сторінкою; у вас може бути одночасно запущено 300 таких запитів, і якщо припустити, що не відбувається блокування, дані кожного запиту будуть зчитуватися в буфер сторінки, сторінка одночасно і ставитись на провід так само швидко, як може клієнт запит і споживання даних. Після того, як всі дані з кожної сторінки будуть надіслані на провід, сторінка стає незачепленою і дуже швидко буде замінена якоюсь іншою сторінкою з диска.

У випадку більш складного запиту, скажімо, наприклад, для агрегування результатів з декількох таблиць, сторінки будуть витягнуті в пам'ять точно так, як вище, ніж цього вимагає процесор запитів. Якщо процесору запитів потрібен тимчасовий робочий простір для обчислення результатів, він знатиме це наперед, коли збирає план для запиту, і запитає робочий простір (пам'ять) від SQLOS . У якийсь момент SQLOS (якщо він не вичерпується ) надасть цю пам'ять процесору запитів, після чого обробка запитів буде відновлена. Якщо процесор запитів помилився в своїй оцінці, скільки пам'яті потрібно запитати у SQLOS, можливо, знадобиться виконати "розлив на диск"операція, коли дані тимчасово записуються в tempdb в проміжному вигляді. Сторінки, записані в tempdb, будуть відкритими, як тільки вони будуть записані в tempdb, щоб звільнити місце для читання інших сторінок в пам'яті. Врешті-решт запит повернеться до даних, що зберігаються у tempdb, підключаючи їх, використовуючи прив'язку, до сторінок у буфері, які позначені вільними.

Мені, безперечно, не вистачає безліч технічних деталей у наведеному вище резюме, але я думаю, що це відображає суть того, як SQL Server може обробляти більше даних, ніж вміщається в пам'яті.


З цікавості, який запит витягує 7 ГБ даних? Я сподіваюся, що це пакетний процес.
datagod

Напевно, не так багато, і ви маєте рацію, сподіваємось, це буде пакетний процес. Мені було просто цікаво побачити, як SQL буде обробляти цей запит
Дастін

5

Я не можу говорити про те, що саме зробив би ваш запит у цьому сценарії, але SQL Server має кілька варіантів залежно від того, скільки потрібно.

  • Дані можуть "розпливатись" до TempDB, для цього використовується ваш диск
  • Старі сторінки можуть бути витіснені з кеш-пам'яті
  • SQL Server може завантажувати деякі сторінки в буфер кешу, використовувати їх, а потім обертати нові сторінки

Найкращий спосіб з’ясувати, що трапиться, - це створити сценарій у середовищі розробників та з’ясувати це.


2

Моє запитання полягає в тому, як SQL Server обробляє запит, який потребує залучення більшої кількості даних в кеш-пам'ять, тоді є вільний простір

Щоб відповісти на цю конкретну частину, дозвольте мені розповісти, як цим керувати. Сторінки розміром 8 КБ. Якщо ви запускаєте запит із запитом великого набору даних, який вимагає введення численних сторінок у пам'ять, SQL Server не принесе всі сторінки за один раз. Він знайде конкретні сторінки і приведе по одній одній сторінці 8 КБ в пам'ять, прочитавши дані з неї і дасть результат, і це буде продовжуватися зараз, припустимо, що вона стикається з ситуацією, коли пам’яті менше, у цьому випадку старі сторінки будуть перероблені диск на зразок @Max вказував. Як ви правильно здогадалися, ця низька пам'ять може сповільнити роботу, оскільки деякий час буде витрачено на видалення старих сторінок. Ось тут контрольно-пропускний пункт та Lazywriterвступає в картину. Lazywriter - це їх переконання, що завжди знайдеться вільна пам'ять, щоб принести нові сторінки на диск. Якщо виникає низький вільний буфер, він спрацьовує та створює вільні пробіли для нових сторінок.

EDIT

Я це розумію, але частина, яка мене трохи бентежить, - це те, що станеться, якщо ви приєднуєтесь \ фільтруючи дані, і ці результати перевищують розмір кешу.

Пам'ять для приєднання та фільтрації вирішується ще до запуску запиту, і припустимо, що дійсно кришиться пам'ять, і пам'ять, необхідна для запуску операції, недоступна. Процесор SQL Server надасть "необхідну пам'ять", яка є

Необхідна пам'ять: Мінімальна пам'ять, необхідна для запуску сортування та хеш-з'єднання. Він називається необхідним, оскільки запит не запустився, коли ця пам'ять не буде доступна. SQL-сервер використовує цю пам'ять для створення внутрішніх структур даних для обробки сортування та хеш-об'єднання.

Так що принаймні запит почне працювати, але під час виконання його цілком ймовірно, що проміжний результат перелиється на Tempdb, що робить його повільним. Я настійно пропоную вам ознайомитись з Поняттям грантів пам'яті запитів


Я це розумію, але частина, яка мене трохи бентежить, - це те, що станеться, якщо ви приєднуєтесь \ фільтруючи дані, і ці результати перевищують розмір кешу. Дані потрібно зібрати для отримання набору повернення, але набір повернення більший, ніж розмір кешу. Чи все ще внутрішній цикл сторінок проходить через кеш, поки він не дає кінцевого результату? Думаю, що вона запише результати в tempdb, оскільки вона перевищила кеш, а потім прочитала з диска це, але не знаю, чи це так
Дастін

2
@Dustin Відредагував мою відповідь, будь ласка, перевіри
Шанкі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.