У меня проблема с относительно простым запросом и планом выполнения, выбранным Access для него.
запрос имеет такую форму
SELECT somethings
FROM A INNER JOIN (B INNER JOIN (C INNER JOIN D ON ...) ON ...) ON ...
WHERE A.primaryKey= 1 AND D.d = 2;
C и D имеют относительно немного строк. A и B содержат несколько тысяч строк.
Запрос, который возвращает 2 строки (не уверен, уместно ли это), очень медленный.Он работает за 17 секунд. Если я удалю часть AND D.d = 2
из предложения where, запрос теперь возвращает 4 строки и выполняется мгновенно.
Насколько я понимаю, механизм JET может мгновенно запустить запрос без фильтра на D.d, а затем мгновенно выполнить указанный фильтр (только 4 строки для фильтрации). Поэтому выполнение запроса с фильтром D.d = 2
не должно занимать слишком много времени.
Я попытался создать подзапрос без фильтра и включить его в другой запрос, который просто отфильтровал бы результат, но он все равно медленный. Я предполагаю, что движок JET достаточно умен, чтобы «сгладить» подзапросы, чтобы результат был таким же.
Поскольку мне не удалось запустить запрос, как я хотел, я использовал штуку JETSHOWPLAN, чтобы Access выводил его план выполнения. Вот что я обнаружил:
Для быстрого запроса (без Dd = 2
) первым шагом плана запроса является применение фильтра A.primaryKey = 1
на столе А. В результате получается набор данных из 1 строки из более чем 30000. Тогда кажется, что соединения выполняются от A до D с использованием индекса с набором данных, который никогда не превышает 4 строк.
Кажется, что медленный запрос выполняется в обратном порядке. Сначала соединяются D и C, затем проверяется D.d = 2
. После этого выполняются соединения от C до A. Таким образом объем данных, которые необходимо соединить от D к C, от C к B и от B к A, будет намного больше. Когда все операции JOIN выполнены и до выполнения A.primaryKey = 1
, набор данных будет содержать 120 КБ строк.
Есть ли способ принудительно составить правильный план запроса в Access?
Надеюсь, я был ясен. Сообщите мне, следует ли опубликовать планы запросов. Я не сделал этого, потому что они довольно большие.
Заранее спасибо,
mp