запрос выбора оракула - индекс по нескольким столбцам - PullRequest
3 голосов
/ 26 апреля 2010

Я работаю над SQL-запросом и пытаюсь его оптимизировать, потому что выполнение его занимает слишком много времени.

У меня есть несколько вариантов выбора и UNION между ними. Каждый выбор находится в той же таблице, но с другим условием в предложении WHERE. В основном у меня всегда что-то вроде:

select * from A
where field1 <=TO_DATE ('01/01/2010', 'DD/MM/YYYY')
AND field1 >= TO_DATE(some date)
and field2 IN (...)

UNION 
select * from A
where field1 <=TO_DATE ('01/01/2010', 'DD/MM/YYYY')
AND field1 >= TO_DATE(some date2)
and field2 =(...)

UNION
....

У меня есть индекс по field1 (это поле даты, а field2 это число). Теперь, когда я делаю выбор, и если я ставлю только

WHERE field1 <TO_DATE ('01/01/2010', 'DD/MM/YYYY')

не использует индекс. Я использую жабу, чтобы увидеть объяснение, и он сказал:

SELECT STAITEMENT Optimiser Mode = CHOOSE
TABLE ACCESS FULL 

Это огромная таблица, и индекс в этом столбце есть.

Есть идеи об этом оптимизаторе? И почему он не использует индекс?

Другой вопрос: если у меня есть предложение where для field1 и field2, я должен создать только один индекс или один индекс для каждого поля?

Ответы [ 5 ]

1 голос
/ 26 апреля 2010

Разве вам не было бы лучше без Союза и вместо этого использовать ИЛИ между различными пунктами?

select * from A
where (
  field1 <"toto"
  and field2 IN (...)
)
OR
(
  field1 >"toto2"
  and field2 IN (...)
)
OR
....

Также возможно иметь индекс на 2 столбца.

CREATE INDEX index_name
ON A (field1, field2);
0 голосов
/ 26 апреля 2010
  • Поскольку вы имеете дело с датами для field1, вы хотите использовать TO_DATE . Например, WHERE field1 < TO_DATE('2010/12/12 12:00:00', 'yyyy/mm/dd hh24:mi:ss').

  • Какой тип индекса имеет поле? Я предполагаю, что индекс b-дерева, и в этом случае оператор менее чем в порядке, но оптимизатор может решить не использовать его в зависимости от текущей статистики таблицы. Если вы хотите принудительно использовать индекс, вы можете указать его в подсказке и посмотреть, как это влияет на производительность.

    SELECT /*+ index(tbl.INDEX_NAME) */<br> tbl.*<br> FROM A tbl WHERE field1 < TO_DATE('2010/12/12 12:00:00','yyyy/mm/dd hh24:mi:ss');

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

0 голосов
/ 26 апреля 2010

Я не самый большой эксперт по Oracle, но я думаю, что вы не можете получить преимущество от индекса при использовании операторов «>» или «<». Индексирование обеспечивает быстрый способ поиска определенных значений, а не диапазона значений. Поэтому, когда вы ищете значения «меньше» определенного значения, индекс ничего не делает. </p>

0 голосов
/ 26 апреля 2010

Есть идеи об этом оптимизаторе? И почему он не использует индекс?

Скорее всего, потому что это условие

field1 < '12/12/2010'

возвращает все или почти все строки.

В этом случае FULL TABLE SCAN лучше.

Другой вопрос: если у меня есть предложение where для field1 и field2, я должен создать только один индекс или один индекс для каждого поля?

Для этого запроса:

select * from A
where field1 <"toto"
and field2 IN (...)

, вам нужно создать составной индекс:

CREATE INDEX ix_a_2_1 ON A (field2, field1)

Это будет использовать INLIST ITERATOR, чтобы разбить запрос на несколько непрерывных диапазонов, и использовать INDEX RANGE SCAN, чтобы вернуть значения из каждого диапазона.

0 голосов
/ 26 апреля 2010

Вы можете создать один индекс для обоих столбцов. Но ваш вопрос рассматривает field1 как строку выше, а затем как дату ниже. Это намеренно? Также оптимизатор выбирает исходя из того, что думает. Так что ваша статистика актуальна? Если нет, то может показаться, что FTS - лучший способ найти нужные записи.

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