Почему операторы SQL так долго, когда «ограничены»? - PullRequest
1 голос
/ 27 апреля 2009

рассмотрим следующую инструкцию pgSQL:

SELECT DISTINCT some_field 
  FROM some_table 
  WHERE some_field LIKE 'text%' 
  LIMIT 10;

Также учтите, что some_table состоит из нескольких миллионов записей и что some_field имеет индекс b-дерева.

Почему запрос выполняется так долго (несколько минут)? Я имею в виду, почему он не перебирает создание набора результатов, и как только он получает 10 из них, возвращает результат? Похоже, что время выполнения одинаково, независимо от того, используете ли вы «LIMIT 10» или нет.

Это правильно или я что-то упустил? Могу ли я что-нибудь сделать, чтобы вернуть первые 10 результатов и «привинтить» остальные?

ОБНОВЛЕНИЕ: если вы отбрасываете отчет, результаты возвращаются практически мгновенно. Однако я знаю, что многие из записей some_table уже довольно уникальны, и, конечно, когда я запускаю запрос без отдельного объявления, первые 10 результатов фактически уникальны. Я также исключил предложение where (исключив его как фактор). Итак, мой оригинальный вопрос все еще остается, почему он не заканчивается, как только найдено 10 совпадений?

Ответы [ 5 ]

8 голосов
/ 27 апреля 2009

У вас есть ОТЛИЧИЕ. Это означает, что для поиска 10 отдельных строк необходимо сканировать все строки, которые соответствуют предикату, до тех пор, пока не будет найдено 10 различных some_fields.

В зависимости от ваших индексов оптимизатор запросов может решить, что сканирование всех строк - лучший способ сделать это.

10 различных строк могут представлять 10 миллионов, бесконечность нечетких строк.

3 голосов
/ 27 апреля 2009

Можете ли вы опубликовать результаты выполнения EXPLAIN по запросу? Это покажет, что Postgres делает для выполнения запроса, и, как правило, является первым шагом в диагностике проблем производительности запросов.

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

Является ли поле some_field уникальным? Если нет, то было бы бесполезно находить разные записи. Если это так, то предложение DISTINCT было бы ненужным, поскольку этот индекс уже гарантирует уникальность каждой строки в поле some_field.

2 голосов
/ 27 апреля 2009

В любое время, когда есть операция, которая включает агрегирование, и «DISTINCT», безусловно, подходит, оптимизатор собирается выполнить агрегирование, даже не задумываясь о том, что будет дальше. А интеграция означает сканирование всей таблицы (в вашем случае с использованием сортировки, если нет индекса).

Но наиболее вероятным прерывателем сделки является то, что вы группируете операцию по столбцу, а не по значению простого столбца. Оптимизатор обычно игнорирует ряд возможных операций, если вы выполняете какое-либо преобразование столбца. Вполне возможно, недостаточно умен, чтобы знать, что порядок "LIKE 'text%'" и "= 'text'" одинаков для целей группировки.

И помните, что вы выполняете агрегирование операции над столбцом.

0 голосов
/ 27 апреля 2009

насколько большой стол? у вас есть какие-либо индексы на столе? проверьте свой план выполнения запроса, чтобы определить, выполняет ли он сканирование таблицы, сканирование индекса или поиск индекса. если он выполняет сканирование таблицы, то, скорее всего, у вас нет индексов.

попробуйте добавить индекс в поле, по которому вы фильтруете, и / или в поле по вашему выбору.

0 голосов
/ 27 апреля 2009

Я подозреваю, что это потому, что у вас нет ЗАКАЗА. Без заказа вам, возможно, придется просмотреть целую кучу записей, чтобы получить 10, которые соответствуют вашему критерию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...