Позвольте мне сначала убедиться, что я правильно понимаю вопрос:
- Вы хотите ускорить
SELECT .. WHERE C_D IS NULL
, но вы не хотите ускорить любой иззапросы, которые ищут ненулевой C_D. - Вы также хотите убедиться, что в индексе нет «ненужных» ненулевых значений, чтобы сэкономить место.
Если этопонимание правильное, тогда вам нужен функциональный индекс.I'e.индекс для функции в поле, а не само поле ...
CREATE INDEX T_IE1 ON T (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) COMPRESS
..., которое вы затем запросите как ...
SELECT * FROM T WHERE (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1
... которыйэквивалентно ...
SELECT * FROM T WHERE C_D IS NULL
... но быстрее, так как он использует индекс:
Это экономит место, потому что индексы из одного столбца делаютне хранить NULL.Кроме того, используйте COMPRESS
, поскольку индекс будет содержать только один ключ, поэтому нет необходимости тратить пространство на повторение одного и того же ключа снова и снова в структуре индекса.
ПРИМЕЧАНИЕ. В Oracle 11 вы могли бытакже создайте виртуальный столбец на основе функций (на основе приведенного выше выражения CASE
), затем индексируйте и запросите этот столбец напрямую, чтобы сохранить некоторую повторяемость ввода.
-- РЕДАКТИРОВАТЬ ---
Если вы также заинтересованы в запросе C_I вместе с C_D IS NULL
, вы можете ...
CREATE UNIQUE INDEX T_IE2 ON T (C_I, CASE WHEN C_D IS NULL THEN 1 ELSE NULL END)
... и запросить егос (например) ...
SELECT * FROM T WHERE C_I > 'some value' AND (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1
... что эквивалентно ...
SELECT * FROM T WHERE C_I > 'some value' AND C_D IS NULL
... но быстрее, так как он использует индекс T_IE2
.
Это фактически единственный индекс, который вам нужен для вашей таблицы (он «покрывает» первичный ключ, поэтому вам больше не нужен отдельный индекс только для C_I).Это также означает, что одинаковые ROWID никогда не сохраняются в более чем одном индексе, что экономит пространство.
ПРИМЕЧАНИЕ: COMPRESS
больше не имеет смысла для индекса T_IE2
.
-- РЕДАКТИРОВАТЬ 2 ---
Если вы заботитесь о простоте больше, чем о пространстве, вы можете просто создать составной индекс для {C_I, C_D}.Oracle хранит значения NULL в составном индексе, пока в одном кортеже есть хотя бы одно значение, отличное от NULL:
CREATE UNIQUE INDEX T_IE3 ON T (C_I, C_D)
Используется индекс:
SELECT * FROM T WHERE C_I > 1 AND C_D IS NULL
Как и в предыдущемРЕДАКТИРОВАТЬ, это единственный индекс, который вам нужен на вашем столе.