sql >> Databasteknik >  >> RDS >> Oracle

Oracle 11 Index endast för en del av datan

Låt mig först se till att jag förstår frågan korrekt:

  • Du vill påskynda SELECT .. WHERE C_D IS NULL men det gör du inte vill påskynda alla frågor som söker efter en icke-NULL C_D.
  • Du vill också se till att inga "onödiga" icke-NULL-värden finns i indexet, för att spara utrymme.

Om den förståelsen är korrekt behöver du en funktionell index. Jag e. ett index på en funktion på ett fält, inte ett fält i sig...

CREATE INDEX T_IE1 ON T (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) COMPRESS

...som du sedan skulle fråga som...

SELECT * FROM T WHERE (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1

...vilket motsvarar...

SELECT * FROM T WHERE C_D IS NULL

...men snabbare eftersom den använder indexet:

Detta sparar utrymme eftersom index med en kolumn inte lagrar NULL. Använd också COMPRESS eftersom index någonsin bara kommer att innehålla en nyckel så det finns ingen anledning att slösa utrymme på att upprepa samma nyckel om och om igen i indexstrukturen.

OBS:Under Oracle 11 kan du också skapa en funktionsbaserad virtuell kolumn (baserat på CASE uttryck ovan), indexera och fråga sedan direkt i den kolumnen för att spara en del upprepad skrivning.

--- REDIGERA ---

Om du också är intresserad av att fråga på C_I tillsammans med C_D IS NULL , du kan...

CREATE UNIQUE INDEX T_IE2 ON T (C_I, CASE WHEN C_D IS NULL THEN 1 ELSE NULL END)

...och fråga den med (till exempel)...

SELECT * FROM T WHERE C_I > 'some value' AND (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1

...vilket motsvarar...

SELECT * FROM T WHERE C_I > 'some value' AND C_D IS NULL

...men snabbare, eftersom den använder indexet T_IE2 .

Detta är faktiskt det enda index som du behöver på ditt bord (det "täcker" primärnyckeln, så du behöver inte längre ett separat index bara på C_I). Vilket också innebär att samma ROWID aldrig lagras i mer än ett index, vilket sparar utrymme.

OBS:COMPRESS inte längre vettigt för index T_IE2 .

--- EDIT 2 ---

Om du bryr dig mer om enkelhet än utrymme kan du bara skapa ett sammansatt index på {C_I, C_D}. Oracle lagrar NULL-värden i sammansatt index så länge det finns minst ett icke-NULL-värde i samma tupel:

CREATE UNIQUE INDEX T_IE3 ON T (C_I, C_D)

Detta använder indexet:

SELECT * FROM T WHERE C_I > 1 AND C_D IS NULL

Som i tidigare EDIT är detta det enda index som du behöver på ditt bord.



  1. django+mysql='DatabaseWrapper'-objektet har inget attribut 'Databas'-fel

  2. Att slå samman två fungerande SQL-frågor ger fel resultat - Var går jag fel

  3. MSSQL cast( [varcharColumn] till int) i SELECT exekveras innan WHERE-satsen filtrerar bort dåliga värden

  4. Välj ett värde från en grupp baserat på ordning från andra kolumner