Access. Программирование на VBA

Повышение производительности запросов


Хотя пользователи могут никогда и не увидеть запрос в приложении, большую часть работы выпол­няют именно запросы. Реляционная база данных была бы бесполезной без возможности выполнять зап­росы к данным. Однако запросы создаются по-разному. Даже если разработчик принял все меры для нормализации данных и создал все необходимые индексы, можно иметь запросы, которые выполняются не так быстро, как могли бы. Может даже существовать два запроса, дающие идентичный результат, но выполняющиеся по-разному.

Чтобы понять, как оптимизировать запросы, необходимо понимать, как их обрабатывает Jet. Каждый запрос проходит четыре этапа:

1. Определение — создается SQL-оператор с помощью одного из нескольких инструментальных средств.

2. Компиляция — SQL-строка разбивается на составные части.

3. Оптимизация — используя алгоритм оценки стоимости. Jet формулирует и тестирует несколько различных способов получения результата, который удовлетворяет данному SQL-оператору.

4. Выполнение — используя план оптимизации, Jet передает результирующий набор пользователю.

Можно определить запрос с помощью QBE Grid, SQL-строки, выполняющейся в коде, SQL-строки в свойстве источника формы, отчета или элемента управления либо с помощью любого другого средства, которое способно создавать SQL-операторы.

Jet размещает составные части строки в иерархической внутренней структуре. Эти части весьма напо­минают ключевые слова SQL-оператора. В основе лежат базовые таблицы, используемые запросом (Из). Потом устанавливаются столбцы результата (Выбор). Далее следуют условия отбора или ограничения, заданные запросом (Где). Затем оцениваются отношения базовых таблиц (Объединение). Наконец, проис­ходит сортировка результирующего набора (Сортировка). Такая структура переходит в фазу оптимизации.

Оптимизация представляет собой самый сложный этап. Jet оценивает и рассчитывает стоимость каж­дого возможного подхода. Это делается путем рассмотрения запроса под двумя различными углами: с точки зрения доступа к базовым таблицам и с точки зрения исследований связей между ними. Понимание действий Jet может способствовать разработке более быстрых запросов в дальнейшем.




Для Jet существует три способа получения строк данных из таблиц:

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



• Индекс. Jet использует индекс таблицы для чтения строк таблицы. Хотя Jet может считывать стра­ницу данных больше чем один раз, такой подход работает намного быстрее, чем сканирование.

• Срочная оптимизация (Rushmorc Optimizations). Этот способ доступен только в тех случаях, когда установлены ограничения более чем для одного индекса в запросе. Срочная оптимизация позволя­ет Jet считать намного меньше страниц данных, иногда вообще ни одной. При использовании способа срочной оптимизации Jet читает только индексные страницы, что весьма эффективно.

Очевидно, что сканирования следует избегать при любой возможности и попытаться воспользоваться индексами. Но как проверить, будет ли для данного запроса действовать лучший способ — срочная оп­тимизация? Срочную оптимизацию нельзя просто включить или выключить, и не существует какого-то явного индикатора для определения этого. Она всегда включена, но лишь определенные виды запросов могут воспользоваться преимуществами данного способа. Для того чтобы была реализована срочная оп­тимизация, должны удовлетворяться следующие три условия:

• Запросы должны содержать множественные индексы.

• Для данных индексированных полей должны быть заданы условные ограничения.

При установке критерия отбора данные индексы должны использоваться одним из трех способов:

• Перекрытие индексов. Условие отбора с оператором AND. Jet может применить способ срочной оптимизации на данном наборе ограничений, поскольку индексированы оба поля.

WHERE CompanyName='Ernst Handle' And City='Graz'

• Объединение индексов. Условие отбора с оператором "OR". Jet может применить способ срочной оптимизации на данном наборе ограничений, поскольку индексированы оба поля.



WHERE CompanyName='Ernst Handle' Or City='Graz'

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

SELECT Count(*) FROM Customers

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

После того как Jet определит способ доступа к данным в отдельных таблицах, он должен определить отношения таблиц между собой. Начинается этап объединения процесса оптимизации. Учитывая сведения о типах соединения, приведенные в табл. 2, можно определить вероятные стратегии соединения плана выполнения.

Таблица 2. Типы объединения: принцип работы и отличительные признаки.

Тип объединения

Принцип работы

Отличительные признаки

Возможное использование

Индексное слияние

Основную работу выполняют индексы.

С обеих сторон связи используются индексы. По крайней мере, один из индексов не допускает нулевых значений (начальное значение). Все таблицы должны соответствовать собственному формату Jet.

Везде, где возможно.

Индекс

Первая таблица сканируется, а затем строки второй таблицы выбираются по индексу.

Существует индекс для связанных полей второй таблицы. В данных индексах  разрешены нулевые значения. Ограничения не используют индексы.

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

Слияние

Обе таблицы сканируются

одновременно

Две таблицы сортируются по связанным полям. В результирующем наборе отображены данные из обеих таблиц.

Обе таблицы достаточно большие и сортируются по связанным полям.

Выборка

Вторая таблица сканируется и сортируется перед объединением.

Нет индексов для связанных полей таблицы.

Когда вторая таблица имеет небольшие размеры и для связанных полей второй таблицы не существует индексов.

Вложенная итерация

Построчная итерация по каждой таблице в отношении.

Ни с одной стороны объединения не существует индексов.

Только для очень малых таблиц и если нет другого выбора.

Jet выбирает один из этих планов в зависимости от таких факторов, как:

• Число записей в каждой базовой таблице,

• Число страниц данных, используемых базовыми таблицами,

• Местонахождение и тип таблицы — локальная ISAM или ODBC,

• Избирательность индексов таблиц — разрешены ли нулевые значения или повторения,

• Число страниц индекса.


Содержание раздела