Автор: Craig Freedman Sequential Read Ahead
Балансировка загрузки процессоров и ввода-вывода очень важна для обеспечения лучшей производительности и оптимизации обслуживания нагрузки сервера. В SQL Server реализованы два механизма асинхронного ввода-вывода: последовательное упреждающее чтение (sequential read ahead) и случайная упреждающая выборка (random prefetching). Оба они предназначены для балансировки нагрузки в многопроцессорных системах.
Чтобы понять, почему асинхронный ввод-вывод так важен,
рассмотрим разницу между пропускной способности конвейеров процессорных ядер и подсистемы
ввода-вывода. Контроллер памяти для современного процессора может обеспечить последовательную
передачу данных со скоростью больше 5 Гбайт в секунду из расчёта на сокете, а случайные
ячейки памяти (в зависимости от того, как вы это будете измерять) может
извлекать со скоростью выше 50 миллионов обращений в секунду. Для сравнения,
жесткий диск SAS 15K класса предприятия может считывать чуть быстрее 125 Мбайт в
секунду последовательно или порядка 200 случайных операций ввода-вывода в
секунду (IOPS). Твердотельные диски (SSD)
могут сократить разницу между производительностью последовательного и случайного
ввода-вывода, исключив из уравнения механическое вращение шпинделя, но «пропасть»
в производительности между процессором и дисками останется. Чтобы сократить
этот разрыв, в серверы нередко устанавливают по 10 и более дисков из расчёта на
каждый сокет. Также важно учитывать и балансировать всю подсистему
ввода-вывода, включая количество и тип дисковых контроллеров, а не только сами
диски, но это не является темой данной статьи.
К сожалению, один логический процессор, обслуживающий только
синхронные операции ввода-вывода, может загрузить только один шпиндель для каждой
инструкции. Чтобы процессор мог эффективно использовать доступную пропускную
способность и IOPS нескольких шпинделей, сервер должен обрабатывать
несколько операций ввода-вывода асинхронно. Таким образом, для достижения этой
задачи в SQL Server
включены вышеупомянутые механизмы упреждающего чтения и выборки. В этой статье мы
рассмотрим последовательное упреждающее чтение.
Когда SQL Server выполняет последовательный просмотр большой таблицы, механизм хранения инициирует упреждающее чтение, которое призвано заранее загрузить страницы в память и подготовить к просмотру до того, как они понадобятся процессору запросов. Механизм упреждающего чтения пытается опережать на 500 страниц нужды просмотра. Мы можем увидеть это в действии, проверив вывод с установкой SET STATISTICS IO ON. Например, я выполнил показанный ниже запрос к базе данных TPC-H с коэффициентом масштабирования 1ГБ. Таблица LINEITEM содержит примерно 6 миллионов строк.
SET STATISTICS IO ON
SELECT COUNT(*) FROM LINEITEM
Table 'LINEITEM'. Scan count 3, logical reads 22328, physical reads 3, read-ahead reads 20331, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Повторное исполнение запроса показывает, что таблица теперь закэширована
в буферном пуле:
SELECT COUNT(*) FROM LINEITEM
Table 'LINEITEM'. Scan count 3, logical reads 22328, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
При анализе производительности последовательного ввода-вывода важно различать просмотр в порядке размещения страниц (в порядке распределения) и просмотр в порядке сортировки индекса. Просмотр в порядке распределения пытается прочитать страницы в том порядке, в котором они физически хранятся на диске, в то время как просмотр в порядке индекса считывает страницы в том порядке, в котором отсортированы данные на страницах индекса.
Обратите внимание, что между логическими томами, которые видит SQL Server, и физическими дисками во многих случаях существует несколько уровней абстракции, таких как RAID массивы или SAN. Таким образом, даже просмотр в порядке распределения может оказаться не оптимально упорядоченным.
Зачастую SQL Server пытается сортировать и читать страницы в порядке распределения даже для просмотра в порядке индекса, поскольку просмотр в порядке распределения, как правило, будет быстрее, поскольку страницы считываются в том порядке, в котором они записаны на диск, что минимизирует число операций поиска на диске. Кучи не имеют внутреннего порядка и, таким образом, для них всегда используется просмотр в порядке распределения. Для индексов просмотр в порядке распределения используется только если уровень изоляции Read Uncommitted (или используется подсказка NOLOCK) и только если процесс запроса не запрашивает упорядоченный просмотр. Дефрагментация индексов помогает обеспечить близкую производительность просмотра с упорядочением по индексу и с упорядочением по распределению.
Комментариев нет:
Отправить комментарий