Как избежать полного сканирования таблицы - PullRequest
1 голос
/ 21 октября 2009

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

SELECT * FROM transactions t LEFT JOIN transac_detail tidts ON (tidts.id_transac = t.id);

Однако меня больше беспокоит тот факт, что Oracle выполняет полное сканирование таблиц в обеих таблицах в соответствии с планом объяснения, хотя t.id и tidts.id_transac имеют индексы.

Есть ли способ оптимизировать это, не касаясь структуры таблицы?

Ответы [ 4 ]

4 голосов
/ 21 октября 2009

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

Я думаю, что ключевой вопрос заключается в следующем: «какая доля строк из каждой таблицы должна быть включена в набор результатов?». Если ответ «100% от каждого», то у вас есть понятный случай для полного сканирования таблицы (и хеш-соединения).

Однако рассмотрим случай, когда таблицы A и B объединены, при этом таблица A содержит 5 строк с внешним ключом для таблицы B (родительской), содержащей миллион строк. Очевидно, что здесь вы будете искать полное сканирование A с присоединением вложенного цикла к B (столбец соединения в таблице B будет проиндексирован, потому что это должен быть первичный или уникальный ключ).

В случае ОП, похоже, вы ожидаете, что 100% строк будут возвращены из каждой таблицы. Я ожидаю увидеть полное сканирование обеих таблиц и хеш-соединение с доступом к транзакциям TRANSACTIONS (возможно, меньшего размера) в первую очередь и встроенным в хеш-таблицу Это был бы оптимальный метод соединения, и я бы просто искал ситуацию, когда TRANSACTIONS слишком велик для однопроходного хеш-соединения. Если при объединении происходит сбой на диске, это может вызвать проблемы с производительностью, и вам придется рассмотреть вопрос об увеличении выделения памяти или равномерном разделении двух таблиц, чтобы уменьшить требования к памяти.

2 голосов
/ 21 октября 2009

Поскольку запрос в том виде, в котором он задан, все равно возвращает все, полное сканирование таблицы может быть самым быстрым способом достижения окончательного результата. Поскольку ввод-вывод обходится дороже, чем процессорное время, может оказаться более эффективным просто вытянуть все данные в память и выполнить там последнее соединение, чем выполнять поиск индекса в цикле по одной таблице.

Чтобы определить, действительно ли запрос может выполняться быстрее, вы можете попробовать следующие подходы:

  • просмотр плана запроса только для подмножества данных (например, для диапазона идентификаторов)
  • попробуйте выполнить запрос для подмножеств разных размеров, посмотрите, какую кривую вы здесь строите
0 голосов
/ 21 октября 2009

У вас нет предложения WHERE, поэтому Oracle думает, что, поскольку он должен возвращать все записи из обеих таблиц, полное сканирование таблицы будет наиболее эффективным.

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

0 голосов
/ 21 октября 2009

Полное сканирование таблицы не обязательно плохо - похоже, что вы не ограничиваете набор результатов каким-либо образом, и это может быть наиболее эффективным способом выполнения запроса. Вы всегда можете проверить это с помощью подсказки индекса и определения результирующего изменения производительности.

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