Индекс в части столбца в оракуле? - PullRequest
2 голосов
/ 01 ноября 2011

В oracle: у меня есть таблица rel с этими столбцами (object_id1, object_id2), которая связывает пары объектов в системе.Object_ids - это varchars, а первые 3 символа определяют тип объекта.Например, пользователи начинают с 001, а книги - с 002, но есть много других типов.Теперь я хотел бы получить все пары книг пользователей, которые связаны в этой таблице с этим запросом:

SELECT * FROM rel WHERE rel.object_id1 LIKE '001%' AND rel.object_id2 LIKE '002%'

Для этого мне понадобится индекс индекса b-дерева для первых трех символовобъект_ид1 и объект_ид2.Можно ли иметь индекс для части столбца, в этом случае первые 3 символа?Как?

Ответы [ 3 ]

5 голосов
/ 01 ноября 2011

Вы можете создать индекс на основе функций

CREATE INDEX idx_rel_obj_id
   ON( substr( object_id1, 1, 3 ),
       substr( object_id2, 1, 3 ) );

Но тогда ваши запросы должны будут использовать те же вызовы функций

SELECT *
  FROM rel
 WHERE substr( rel.object_id1, 1, 3 ) = '001'
   AND substr( rel.object_id2, 1, 3 ) = '002'

Обычно вы создаете пользовательские функции(т.е. get_object_type), которые были помечены как детерминированные и будут использовать эти пользовательские функции как в определении индекса, так и в запросах, чтобы гарантировать, что кто-то случайно не использует другую конструкцию для получения первых трех символов полячто помешало бы использовать индекс на основе функций.

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

2 голосов
/ 01 ноября 2011

Вы можете сделать это с помощью индекса на основе функций.

Предполагая, что:

SQL> create table t (a varchar(10));
Table created.

Затем вы можете создать индекс по первым трем символам этого столбца:

SQL> create index t_s on t(substr(a,0,3));
Index created.

Он будет использоваться, если вы используете ту же самую функцию в своих запросах:

SQL> set autotrace traceonly;
SQL> select * from t where SUBSTR(a,0,3) = '001' ;

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 2699450933

------------------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |     1 |     7 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T    |     1 |     7 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN      | T_S  |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------
...
0 голосов
/ 01 ноября 2011

Если вы не можете изменить физическую схему, чтобы поместить значение типа объекта в отдельный столбец (наиболее эффективный подход), вы можете создать индекс на основе функции для подстроки, используя функцию SUBSTR, что-то вроде:

CREATE INDEX rel_idx_f01 ON rel (SUBSTR(object_id1, 1, 3));

Очевидно, вам понадобится один индекс для каждого из столбцов object_id1 и object_id2.

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