Оптимизация Oracle SQL Query - PullRequest
4 голосов
/ 11 июня 2011

Здравствуйте, у меня есть SQL-запрос, который я пытаюсь оптимизировать.Этот запрос завершается за 0,3 секунды, но мне нужно выполнить один и тот же запрос для множества различных идентификаторов хранилищ. В любом случае можно ли оптимизировать этот запрос, чтобы он выполнялся быстрее, или изменить его так, чтобы он получал все идентификаторы одновременно.

Я всегда могу создать новую команду в C #, которая соответствует команде, чтобы сделать ее объединением множества различных запросов.

select /*+ PUSH_SUBQ */ *  
from mytable r
where r.s in (1, 7)
and r.d in (1, 75)
and r.storeid = 1162
and r.period = 20110528
and r.pid in (select /*+ no_unnest qb_name(subq1) */ 
productid from otherTable where itmid=9999)

Я уже пробовал что-то подобное, но это занимает вечность.

select  /*+ PUSH_SUBQ */ * 
    from mytable r
    where r.s in (1, 7)
    and r.d in (1, 75)
    and r.storeid in (1162, 1223, 1231, 51231, 231, ...)
    and r.period = 20110528
    and r.pid in (select /*+ no_unnest qb_name(subq1) */ 
    productid from otherTable where itmid=9999)

У MyTable есть такие индексы: pid - НЕ УНИКАЛЬНЫЙ, РАЗДЕЛЕННЫЙ, НЕТ JOIN_INDEX для всех остальных столбцовУНИКАЛЬНЫ, РАЗДЕЛЕНЫ, НЕТ JOIN_INDEX

Ответы [ 5 ]

5 голосов
/ 11 июня 2011

Попробуйте запустить Oracle EXPLAIN PLAN по вашему запросу.Он должен выделять проблемные области и может помочь сузить узкие места либо в самом запросе, либо в запрашиваемых таблицах.

Использование EXPLAIN PLAN: http://download.oracle.com/docs/cd/B10500_01/server.920/a96533/ex_plan.htm

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

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

Возможно, вы захотите запустить расширенную трассировку SQL и либо прочитать трассировку вручную, либо запустить ее через профилировщик.

Изменить запрос, чтобы получить «все storeids одновременно», очень просто - полностью удалить условие для storeid. Если вам действительно нужны результаты для каждого возможного storeid, вы, скорее всего, тратите много времени на повторное рассмотрение блоков, выполняя по одному запросу для каждого. Но, может быть, под «всеми магазидами» вы подразумевали весь небольшой набор идентификаторов.

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

Если вам нужно, чтобы это работало для многих разных магазинов, вы, вероятно, либо указали бы список различных значений StoreID, т.е.

select *  
  from mytable r
 where r.s in (1, 7)
   and r.d in (1, 75)
   and r.storeid IN( 1162, 1163, 1164, ... )
   and r.period = 20110528
   and r.pid in (select productid 
                   from otherTable 
                  where itmid=9999)

Если вы хотите оптимизировать производительность запроса, вам необходимо предоставить структуру двух таблиц (MyTable и OtherTable), сообщить нам, какие индексы существуют в этих двух таблицах, и дать нам некоторое представление о количестве элементов. различные условия.

Я бы скорее беспокоился о наличии подсказок (особенно подсказки PUSH_SUBQ, которая будет игнорироваться, потому что она не в том месте. Хотя очень редко бывает уместно и необходимо добавлять явные подсказки в запросы, это почти всегда случается так, что когда Oracle генерирует плохой план запроса, базовая статистика вводит в заблуждение оптимизатор. Если это так, то вам гораздо лучше исправить статистику, чем подсказку запроса.

0 голосов
/ 24 августа 2014
 select r.*  
  from mytable r 
   inner join otherTable o on r.pid = o.productid and o.itmid = 9999
  where r.s in (1, 7)
   and r.d in (1, 75)
   and r.storeid IN( 1162, 1163, 1164, ... )
   and r.period = 20110528

Попробуйте этот запрос, это займет гораздо меньше времени.

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

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

select r.d, r.storeid, r.period, r.pid /* select only columns you need */
from mytable r, otherTable o
where r.s in (1, 7)
and r.d in (1, 75)
and r.storeid = 1162
and r.period = 20110528
and r.pid = o.productid /* use a join instead of subquery */
and o.itmid=9999

Измерь и посмотри.

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