Считывание страниц

Процесс ввода-вывода экземпляра компонента SQL Server Database Engine включает физические и логические операции чтения. Логическое чтение выполняется каждый раз, когда компонент Database Engine запрашивает страницу из буферного кэша. Если в этот момент страница не находится в кэше, то сначала при помощи операции физического чтения она копируется в него с диска.

Запросы к экземпляру компонента Database Engine на чтение страниц управляются реляционным механизмом, а их дополнительную оптимизацию выполняет подсистема хранилища. Реляционный механизм подбирает наиболее эффективный метод доступа (просмотр таблицы, просмотр индекса или чтение по ключу). Компонент метода доступа и диспетчер буферов подсистемы хранилища определяют общий шаблон считывания и оптимизируют операции чтения для реализации метода доступа. Поток, выполняющий пакет, планирует операции считывания.

Упреждающее чтение

Компонент Database Engine поддерживает механизм оптимизации производительности, называемый упреждающим чтением. Он заключается в том, что система пытается предугадать, какие именно страницы данных и индексов понадобятся для плана выполнения запроса, и помещает эти страницы в буферный кэш, прежде, чем в них возникнет реальная необходимость. Это позволяет распараллелить операции вычисления и ввода-вывода, полностью задействовав процессорные и дисковые мощности.

Механизм упреждающего чтения позволяет компоненту Database Engine считывать из одного файла до 64 последовательных страниц (512 КБ). Эта операция выполняется как единая последовательность разборки-сборки для соответствующего числа буферов в буферном кэше (возможно, расположенных не последовательно). Если какая-либо из страниц этого диапазона уже присутствует в буферном кэше, то соответствующая страница по окончании считывания будет удалена из памяти. Кроме того, диапазон страниц может быть «усечен» с начала или с конца, если соответствующие страницы уже находятся в кэше.

Упреждающее чтение бывает двух видов: для страниц данных и для страниц индексов.

Чтение страниц данных

Просмотр таблиц для чтения страниц данных выполняется в компоненте Database Engine весьма эффективно. Страницы карты распределения индекса (IAM) в базе данных SQL Server содержат указатели на экстенты, занятые таблицей или индексом. Подсистема хранилища может считывать IAM для построения отсортированного списка адресов на диске, которые необходимо считать. Это позволяет подсистеме хранилища оптимизировать операции ввода-вывода выполняемые последовательно в виде больших операций чтения на основе их размещения на диске. Дополнительные сведения о страницах IAM см. в разделе Управление дисковым пространством, занятым объектами.

Считывание страниц индекса

Подсистема хранилища считывает страницы индекса последовательно, в порядке значений ключей. На приведенном ниже рисунке показан пример упрощенного представления набора конечных страниц, которое содержит набор ключей и промежуточный узел индекса, сопоставляющий концевые страницы. Дополнительные сведения о структуре страниц в индексе см. в разделе Структуры кластеризованного индекса.

Промежуточные узлы индекса соответствуют страницам конечного уровня по ключу

Подсистема хранилища использует данные промежуточной страницы индекса выше конечного уровня для организации последовательного упреждающего чтения страниц, содержащих значения ключей. При обработке запроса на все ключи от «ABC» до «DEF» вначале подсистема хранилища считывает страницу индекса выше конечной страницы. Однако он не просто последовательно считывает все страницы данных от 504-й до 556-й, то есть последней, на которой находятся значения ключей заданного диапазона. Вместо этого подсистема хранилища просматривает промежуточную страницу индекса и строит список конечных страниц для считывания. Затем подсистема хранилища планирует все операции ввода-вывода в порядке следования ключей. Кроме того, подсистема хранилища определяет, что страницы 504/505 и 527/528 являются смежными, и считывает содержащиеся на них данные за одну операцию, после чего выполняет сборку данных. Если в последовательной операции необходимо получить много страниц, то планируется целый блок операций чтения за один раз. По завершении этого подмножества операций чтения планируется такое же количество новых, и так до тех пор, пока все нужные страницы не будут запрошены.

Затем подсистема хранилища использует упреждающую выборку для ускорения поиска в таблицах по некластеризованным индексам. Конечные строки в некластеризованном индексе содержат указатели на строки данных, в которых хранятся все определенные значения ключей. По мере чтения по конечным страницам некластеризованного индекса подсистема хранилища также начинает планирование асинхронных операций чтения строк данных по уже полученным указателям на них. Это позволяет приступить к извлечению строк данных из базовой таблицы еще до завершения просмотра некластеризованного индекса. Этот процесс выполняется независимо от наличия в таблице кластеризованного индекса. SQL Server Enterprise использует упреждающую выборку в большей степени, чем другие выпуски SQL Server, выполняя упреждающее чтение большего числа страниц. Уровень упреждающей выборки нельзя настраивать ни в одном из выпусков. Дополнительные сведения о некластеризованных индексах см. в разделе Структуры некластеризованных индексов.

Расширенный просмотр

Функция расширенного просмотра в выпуске SQL Server Enterprise позволяет нескольким задачам совместно выполнять полный просмотр таблиц. Если план выполнения инструкции Transact-SQL требует просмотра страниц данных таблицы, а компонент Database Engine обнаружил, что таблица уже просматривается другим планом выполнения, то вторая операция просмотра будет присоединена к первой в том месте, где она в данный момент находится. Компонент Database Engine считывает по странице за раз и передает полученные строки каждой считываемой страницы обоим планам выполнения. Это продолжается до тех пор, пока не будет достигнут конец таблицы.

На этой стадии первый план выполнения получит полные результаты просмотра, а второй план до сих пор не получил страницы данных, находящиеся ранее места присоединения. Поэтому для него производится возврат к первой странице данных, и просмотр повторяется до этой точки. Таким образом, можно объединять любое количество просмотров. Компонент Database Engine продолжает циклическое считывание страниц данных до тех пор, пока не будут завершены все операции просмотра. Этот механизм называется также «кольцевым просмотром» и демонстрирует, почему порядок строк, возвращаемых в результате выполнения инструкции SELECT, без предложения ORDER BY не гарантирован.

Например, допустим, что некая таблица содержит 500 000 страниц. Пользователь UserA выполняет инструкцию Transact-SQL, которая требует просмотра таблицы. По первому запросу просмотрено уже 100 000 страниц, после чего пользователь UserB выполняет еще одну инструкцию Transact-SQL, которая требует просмотра той же таблицы. Для считывания после 100 001-ой страницы компонент Database Engine запланирует всего одну серию запросов и будет возвращать полученные строки обоим планам выполнения. По достижении 200 000-ой страницы пользователь UserC выполняет еще одну инструкцию Transact-SQL, которая требует просмотра той же таблицы. Начиная с 200 001-ой страницы, компонент Database Engine будет передавать строки каждой считываемой страницы всем трем просмотрам. После считывания 500 000-ой строки просмотр для пользователя UserA завершается, а для пользователей UserB и UserC чтение снова начинается с первой страницы. Когда компонент Database Engine доходит до 100 000-ой страницы, просмотр для пользователя UserB завершается. Просмотр для пользователя UserC продолжает выполняться до тех пор, пока не будет достигнута 200 000-ая страница. Только после этого операция просмотра для всех пользователей будет завершена.

Без возможности расширенного просмотра все пользователи были бы вынуждены конкурировать за буферное пространство, что вызвало бы значительную нагрузку на дисковый накопитель. Затем те же страницы считывались бы каждым из пользователей, вместо того чтобы загрузить их один раз для нескольких пользователей.