2008-09-29 2 views
14

Предположим, у меня есть таблица базы данных с двумя полями «foo» и «bar». Ни один из них не является уникальным, но каждый из них индексируется. Однако, вместо того, чтобы индексироваться вместе, у каждого из них есть отдельный индекс.Может ли несколько индексов работать вместе?

Теперь предположим, что я выполняю такой запрос, как SELECT * FROM sometable WHERE foo='hello' AND bar='world'; В моей таблице огромное количество строк, для которых foo является «hello», и небольшое количество строк, для которых bar является «миром».

Таким образом, наиболее эффективной задачей для сервера базы данных, выполняемой под капотом, является использование индекса штриха для поиска всех полей, где bar является «миром», а затем возвращать только те строки, для которых foo является «hello». Это O(n) где n - количество строк, где bar является «миром».

Однако, я думаю, возможно, что процесс произойдёт в обратном порядке, где используется индекс fo и результаты поиска. Это будет O(m) где m - количество строк, где foo - «hello».

Итак, Oracle достаточно умна, чтобы эффективно искать здесь? Как насчет других баз данных? Или я могу сказать это в своем запросе для поиска в правильном порядке? Возможно, положив bar='world' первым в статье WHERE?

ответ

11

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

Кроме того, Oracle может комбинировать использование обоих индексов несколькими способами - он может преобразовывать индексы btree в растровые изображения и выполнять на них растровую ANd-операцию или может выполнять хеш-соединение на rowid, возвращенном два индекса.

Одним из важных соображений здесь может быть любая корреляция между запрошенными значениями. Если foo = 'hello' учитывает 80% значений в таблице, а bar = 'world' - 10%, то Oracle собирается оценить, что запрос вернет 0.8 * 0.1 = 8% строк таблицы. Однако это может быть неверным - запрос может фактически вернуть 10% от rwos или даже 0% строк в зависимости от того, насколько коррелированы значения. Теперь, в зависимости от распределения этих строк по всей таблице, может оказаться неэффективным использовать индекс для их поиска. Вам все равно может потребоваться (скажем) 70% или табличные блоки для получения требуемых строк (google для «фактора кластеризации»), и в этом случае Oracle собирается выполнить проверку полной таблицы, если она правильно оценивает оценку.

В 11g вы можете собирать многоколоночную статистику, чтобы помочь в этой ситуации, я полагаю. В 9i и 10g вы можете использовать динамическую выборку, чтобы получить очень хорошую оценку количества возвращаемых строк.

Чтобы получить план выполнения этого:

explain plan for 
SELECT * 
FROM sometable 
WHERE foo='hello' AND bar='world' 
/
select * from table(dbms_xplan.display) 
/

Контраст, что с:

explain plan for 
SELECT /*+ dynamic_sampling(4) */ 
     * 
FROM sometable 
WHERE foo='hello' AND bar='world' 
/
select * from table(dbms_xplan.display) 
/
3

Да, вы можете дать «подсказки» с запросом к Oracle. Эти подсказки замаскированы как комментарии («/ * HINT * /») в базу данных и в основном зависят от поставщика. Таким образом, одна подсказка для одной базы данных не будет работать в другой базе данных.

Я бы использовал указательные подсказки здесь, первый намек на маленький стол. См. here.

С другой стороны, если вы часто просматриваете эти два поля, почему бы не создать индекс на этих двух? У меня нет правильного синтаксиса, но это было бы что-то вроде

CREATE INDEX IX_BAR_AND_FOO on sometable(bar,foo); 

Таким образом, поиск данных должен быть довольно быстрым. И в случае, если конкатенация уникальна, вы просто создаете уникальный индекс, который должен быть молниеносным.

+0

Informix также содержит эти предложения. В большинстве случаев вы не идете _help_ оптимизатора таким образом - это хорошо, что он делает. – hometoast 2008-09-29 15:16:49

+0

К сожалению, у меня есть таблица с большим количеством столбцов, каждая со своим индексом. Пользователи могут запрашивать любую комбинацию полей, поэтому я не могу эффективно создавать индексы для каждой комбинации полей. Но если бы у меня было только два поля, требующие индексов, я бы полностью согласился с вашим предложением использовать два индекса. – 2008-09-29 15:51:57

+0

Не пытайтесь даже извиниться:). Oracle, скорее всего, будет использовать «самый чувствительный» в вашем случае. Опять же, вы не должны полагаться только на оптимизацию Oracle. Но, с одной стороны, обновление плана объяснений и попытка сохранить его в актуальном состоянии - это хорошая идея. – Georgi 2008-09-30 00:11:22

2

Значит, Oracle достаточно умна, чтобы эффективно искать здесь?

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

1

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

+0

«План» - это именно то, что он планирует сделать в первую очередь. Бывают моменты, когда это отклоняется от того, что на самом деле происходит. Вам нужно создать трассировку, чтобы получить именно то, что произошло. – 2008-10-07 18:37:47

1

Вы можете указать, какой индекс использовать. Я не знаком с Oracle, но в Mysql вы можете использовать USE | IGNORE | FORCE_INDEX (см. here для получения дополнительной информации). Для лучшей производительности, хотя вы должны использовать комбинированный индекс.

1

Лучшим подходом было бы добавить foo в индекс bar или добавить строку в индекс foo (или оба). Если индекс foo также содержит индекс на баре, этот дополнительный уровень индексации не повлияет на полезность индекса foo при любом текущем использовании этого индекса и не окажет заметного влияния на производительность поддержания этого индекса, но он даст дополнительную базу данных информацию для работы с оптимизацией запросов, например, в примере.

+0

На самом деле я согласен с Джеффри ... в дополнение к тому, что он сказал, имея два отдельных индекса, повлияет на вашу скорость записи (потому что база данных должна обновлять два индекса при записи вместо одного. – 2008-09-29 15:27:24

1

Это лучше, чем это.

Индекс Ищет всегда быстрее, чем полное сканирование таблицы. Поэтому за кулисами Oracle (и SQL-сервер, если на то пошло) сначала найдет диапазон строк по обоим индексам. Затем он посмотрит, какой диапазон короче (видя, что это внутреннее соединение), и он будет итерировать более короткий диапазон, чтобы найти совпадения с большим из двух.

+1

Во-первых, это неверно, что индекс поисковые запросы всегда быстрее, чем полное сканирование таблицы. В Oracle многокадровые чтения для полного сканирования таблицы могут быть быстрее, чем одноблочные чтения индексов, если вы извлекаете более чем небольшую часть строк. – 2008-09-29 15:46:46

+1

Во-вторых, оптимизатор Oracle будет не сканировать два индекса, чтобы определить, для чего они будут использоваться, он будет использовать статистику в словаре данных, чтобы определить, какой индекс будет более избирательным. На эти статистические данные будут влиять гистограммы, которые определяют селективность разных значений. – 2008-09-29 15:49:15

2

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

Как минимум, если оптимизатор может определить избирательность конкретного условия, он будет использовать более избирательный индекс (т. Е. Индекс на панели). Но если у вас есть перекошенные данные (в столбце есть N значений, но избирательность любого конкретного значения существенно больше или меньше 1/N данных), вам нужно будет иметь гистограмму в столбце, чтобы сообщить оптимизатор, значения которого более или менее вероятны. И если вы используете переменные связывания (как и все хорошие разработчики OLTP), в зависимости от версии Oracle у вас могут возникнуть проблемы с зависанием переменных.

Потенциально Oracle может даже преобразовывать два индекса b * -tree в битмапы и комбинировать растровые изображения, чтобы использовать оба индекса для поиска строк, которые ему нужно получить. Но это довольно необычный план запроса, особенно если есть только два столбца, где один столбец является высокоселективным.

3

Эли,

В комментарии Вы писали:

К сожалению, у меня есть таблица с большим количеством столбцов каждый со своим собственным индексом. Пользователи могут запрашивать любую комбинацию полей, поэтому я не могу эффективно создавать индексы для каждой комбинации полей.Но если бы у меня было только два поля, требующие индексов, я бы полностью согласился с вашим предложением использовать два индекса. - Eli Courtwright (29 сентября в 15:51)

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

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

На всякий случай кто-то скажет, что ИМТ предназначены только для столбцов с низкой мощностью и могут не применяться к вашему делу. Низкий, вероятно, не такой маленький, как вы думаете. Единственной реальной проблемой является параллелизм DML в таблице. Для этого нужно быть однопоточным или редким.

Смежные вопросы