Оптимизировать SQL с Interbase - PullRequest
0 голосов
/ 17 марта 2010

Меня вдохновили хорошие ответы на мой предыдущий вопрос о SQL. Теперь этот SQL запускается на БД с Interbase 2009. Его размер составляет около 21 ГБ.

SELECT DistanceAsMeters, AddrDistance.Bold_Id, AddrDistance.Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity
FROM AddrDistance
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id
Where  DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0
       and not AddrDistance.bold_id in (select bold_id from DistanceQueryTask)
Order By Created Desc

Есть 840000 строк с AddrDistance 190000 строк с адресом и 4 с DistanceQueryTask.

Вопрос в том, можно ли сделать это быстрее? Я полагаю, один и тот же запрос выполняется много раз , выберите bold_id из DistanceQueryTask . Обратите внимание, что меня не интересуют хранимые процедуры, просто SQL:)

РЕДАКТИРОВАТЬ1 Вот текущий план выполнения:

Statement: SELECT DistanceAsMeters, AddrDistance.Bold_Id, AddrDistance.Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity
FROM AddrDistance
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id
Where  DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0
       and not AddrDistance.bold_id in (select bold_id from DistanceQueryTask)
Order By Created Desc

PLAN (DISTANCEQUERYTASK INDEX (RDB$PRIMARY218))
PLAN SORT (JOIN (JOIN (ADDRDISTANCE NATURAL,ADDRESSFROM INDEX (RDB$PRIMARY234)),ADDRESSTO INDEX (RDB$PRIMARY234)))

И да, у DistanceQueryTask должно быть небольшое число, если строки в базе данных.

Ответы [ 4 ]

2 голосов
/ 17 марта 2010

Поскольку Даниэль и Андре предлагают, индекс очень помогает.
Я бы предложил этот индекс (DistanceMeters, PseudoDistanceAsCostKm, Bold_id), потому что первые 2 части индекса являются постоянными, а затем - это небольшая часть индекса, необходимая для чтения.

Если существует тот факт, что FromAddress и / или ToAddress существуют, вы можете изменить LEFT JOIN на INNER JOIN, потому что это часто быстрее (оптимизатор запросов может сделать некоторые предположения).

2 голосов
/ 17 марта 2010

Я полагаю, что bold_id - ваш ключ, и, следовательно, правильно проиндексирован.
Тогда замена подвыбора и not ... in объединением может помочь оптимизатору.

SELECT DistanceAsMeters, Bold_Id, Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity
FROM AddrDistance
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id
LEFT JOIN DistanceQueryTask ON AddrDistance.bold_id = DistanceQueryTask.bold_id
Where  DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0
  and DistanceQueryTask.bold_id is null
Order By Created Desc
2 голосов
/ 17 марта 2010

Создать индекс для этой части: (DistanceAsMeters = 0 и PseudoDistanceAsCostKm = 0) потому что он выполняет (плохое) сканирование таблицы: ADDRDISTANCE NATURAL

И попробуйте использовать объединение вместо подвыбора, как указано Франсуа.

2 голосов
/ 17 марта 2010

Использование левого соединения и подзапросов замедлит любой запрос.

Вы можете получить некоторые улучшения с правильными индексами (для Bold_id, DistanceMeters, PseudoDistanceAsCostKm) помните, что больше индексов увеличивает размер базы данных

...