Насколько плох оператор IN для производительности SQL-запроса? - PullRequest
1 голос
/ 23 июня 2011

У меня был SQL-запрос, выполнение которого занимало 9 часов.См. Ниже:

Select Field1, Field2
From A
Where Field3 IN (45 unique values here) 

Когда я разделил этот запрос на 3 абсолютно одинаковых запроса, каждый из которых имел 15 значений в предложении IN, каждому из них потребовалось 2 минуты.Поэтому вместо того, чтобы тратить 9 часов, я теперь трачу 6 минут (3 запроса * 2 минуты).

Может кто-нибудь объяснить, пожалуйста, как практически одинаковые запросы с разницей в количестве значений в предложении IN занимают столько разного времени для выполнения?

Ответы [ 5 ]

2 голосов
/ 23 июня 2011

Вы пытались использовать EXISTS?

 Select Field1, Field2 From A Where
 EXISTS (SELECT NULL FROM B Where
 B.value = A.Value )
2 голосов
/ 23 июня 2011
  • Какой механизм базы данных вы используете (Oracle, SQL Server, MySQL и т. Д.)?
  • Можете ли вы опубликовать план запроса для обоих запросов?

Похоже, оптимизатор, который использует ваша база данных, выбрал очень плохой план выполнения для первого запроса. Предполагая, что ядро ​​вашей базы данных использует какой-то оптимизатор на основе затрат (большинство крупных поставщиков), это обычно означает, что предположение оптимизатора относительно количества возвращаемых строк было совершенно неверным. Скорее всего, его оценки одинаково неверны, независимо от того, указаны ли 15 или 45 уникальных значений, но бывает, что утроение неверной оценки приводит оптимизатора к мысли, что другой план запроса будет уместным. Как правило, это означает, что информация, которую вы дали оптимизатору в терминах статистики по таблице A, неверна и требует исправления.

Как говорится, насколько большой стол A? Если вы действительно запрашиваете из одной таблицы, у оптимизатора есть относительно немного вариантов для рассмотрения. На самом деле нужно только выбрать между полным сканированием таблицы на A и использованием индекса на Field3. Даже если он решит выполнить сканирование таблицы, а не использовать индекс для Field3, ни в коем случае не потребуется 9 часов для сканирования одной таблицы, исключая действительно исключительные обстоятельства, когда таблица A измеряется как минимум сотнями ГБ и аппаратное обеспечение относительно пешеходные.

1 голос
/ 23 июня 2011

Две возможности, которые я вижу:

1) Может быть миллиард записей с Field3 = 10001, так что это будет очень медленно. И может не быть записей с другими значениями, так что это будет очень быстро.

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

0 голосов
/ 23 июня 2011

Сначала убедитесь, что у вас есть индекс для вашего «Field3» в вашей таблице «A», и, если возможно, включите «Field1», «Field2» (охватывающий индекс).Вы не говорите, какую базу данных вы используете, поэтому сложно дать точный совет.

Если это все еще не ускоряет, попробуйте создать временную таблицу, а затем вставьте все "IN "значения, а затем" INNER JOIN "или" WHERE EXISTS "эту временную таблицу для вашей таблицы" A ".

0 голосов
/ 23 июня 2011

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

  • Многократное или ненужноеjoin
  • Количество строк в объединенных таблицах
  • Нет индексов или индексов, не используемых подсистемой запросов
  • Статистика таблиц устарела, что приводит к неэффективности индексов
  • Неэффективноquery

С учетом сказанного вы всегда можете получить лучшее представление о том, как ваш запрос интерпретируется механизмом запросов, запустив EXPLAIN PLAN.Вот информация о том, как это сделать для базы данных Oracle, http://download.oracle.com/docs/cd/B10500_01/server.920/a96533/ex_plan.htm

...