Оператор SQL странно медленный - PullRequest
3 голосов
/ 14 февраля 2011
select TABLE1.FIELD1, 
       TABLE1.FIELD2, 
       TABLE1.FIELD3, 
       TABLE1.FIELD4, 
       TABLE1.FIELD5, 
       TABLE2.FIELD6, 
       TABLE2.FIELD7
  from TABLE1,
       TABLE2
 where TABLE1.FIELD8 = 'value' 
   and TABLE2.FIELD6 = TABLE1.FIELD6;

Я ищу некоторые данные из 2 разных таблиц.(База данных Oracle - поля, проиндексированные для обеих таблиц) Для выполнения вышеуказанного запроса требуется 500 мс.Когда я по отдельности выполняю поиск в таблицах одних и тех же полей, они заканчиваются менее чем за 20 мс.

Я могу искать в TABLE1 нужные мне данные (+ FIELD6), а затем искать в TABLE2 остальные, используя FIELD6.

Мой вопросПочему так медленно, когда я присоединяюсь к столам.Я делаю что-то не так?

РЕДАКТИРОВАТЬ: Добавление плана объяснения оракула

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
| Id  | Operation                    |  Name                   | Rows  | Bytes | Cost  |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                         |  6318 |   586K|   620 |
|   1 |  HASH JOIN                   |                         |  6318 |   586K|   620 |
|   2 |   TABLE ACCESS BY INDEX ROWID| TABLE1                  |  6318 |   450K|     2 |
|   3 |    INDEX RANGE SCAN          | INDEX_TABLE1_FIELD8     |  2527 |       |     1 |
|   4 |   TABLE ACCESS FULL          | TABLE2                  |   430K|  9242K|   508 |
----------------------------------------------------------------------------------------

Note: cpu costing is off, 'PLAN_TABLE' is old version

Ответы [ 5 ]

2 голосов
/ 14 февраля 2011

Медленнее чем?СУБД была создана для присоединения.Если вы думаете, что получите лучшее время отклика, если будете делать это процедурно (строка за строкой, используя курсор для цикла или подобное), вы ошибетесь в 99,9% случаев.

Я полагаю, вы сравниваетеВремя отклика от объединения, которое возвращает все строки (или даже первые 500 или около того строк, если используется FIRST_ROWS), против нескольких записей, возвращаемых процедурно (или вручную).Яблоки и апельсины.

2 голосов
/ 14 февраля 2011

Если в TABLE1 имеется 25 записей, удовлетворяющих field8='value', и если требуется от 20 мс до select ... from table2 where field6=???, то 500 мсек находятся в области ожидаемого времени.

Таким образом, вполне разумно сказать, что каждый запрос занимает 20 мс, вам также нужно указать, сколько записей соответствует условию field8 в TABLE1 и сколько записей в среднем удовлетворяет условию TABLE2.FIELD6.

Но чтобы исключить все догадки, вам нужно, чтобы Oracle объяснил запрос и отобразил (или опубликовал) объясненный план здесь для дальнейшего анализа.

РЕДАКТИРОВАТЬ : Поскольку, как представляется, существует соотношение 1: 1 между критериями (и запрос впоследствии возвращает 1 запись), 500 мс не ожидается. В этом случае я бы действительно подчеркнул необходимость объяснения запроса. Если вы не знакомы с этим, вы можете сделать это так:

explain plan for
   select .... <your entire select statement goes here>
;

select * from table(dbms_xplan.display);

А затем опубликуйте результат. Это позволит нам помочь вам лучше.

1 голос
/ 14 февраля 2011

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

1 голос
/ 14 февраля 2011

Я не вижу ничего плохого в вашем запросе, и (хороший) совет, данный в других ответах, поможет вам понять, что происходит в деталях.

Однако, в принципе, вы должны иметь в виду порядок данных в каждой таблице и то, сгруппированы ли данные или распределены. Все хорошо говорят: «Требуется только 20 мс, чтобы найти», но сколько времени потребуется для сопоставления двух наборов данных?

Если известно, что оба набора данных находятся в одном и том же порядке, СУБД может выровнять их относительно быстро. Но СУБД может знать это только по индексу.

Если у вас есть индекс для Table1, который является Field8, а затем Field6, все «значения» будут объединены вместе, а затем упорядочены Field6. Однако если у вас есть индекс Field6, то Field8, записи, которые вас интересуют, будут упорядочены, но распределены по индексу. Наконец, если у вас нет индексов в этих полях, все будет случайным образом упорядочено и распределено.

В зависимости от этих типов факторов, СУБД может выполнить ваш запрос буквально десятками. Для достижения наилучшей производительности необходимо понять, что должна делать СУБД, а затем дать ей индекс (ы), чтобы сделать ее максимально простой.

1 голос
/ 14 февраля 2011

Вы должны знать, что такое план запроса, используя либо инструмент отчетности, либо такие подсказки, как /*+ gather_plan_statistics */.Найти эту информацию в поисковой системе.

Когда оптимизатор объединяет две таблицы, он может использовать декартово произведение, объединение сортировки-слияния, соединение хеш-функции… Попробуйте SELECT /*+ USE_HASH(table1 table2) */ ….

Также, если оптимизаторвыбирает неправильный план, вы можете пересчитать статистику, если она не является репрезентативной, например, с помощью процедуры DBMS_STATS.GATHER_SCHEMA_STATS.Это основной источник неправильного выбора оптимизатора.

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