LIKE mønstermatchende tilstand forventer at se karaktertyper som både venstre- og højreside-operander. Når den støder på et NUMMER, konverterer den implicit det til char. Din forespørgsel 1 er dybest set lydløst omskrevet til dette:
SELECT a1.*
FROM people a1
WHERE TO_CHAR(a1.id) LIKE '119%'
AND ROWNUM < 5
Det sker i dit tilfælde, og det er dårligt af 2 grunde:
- Konverteringen udføres for hver række, hvilket er langsomt;
- På grund af en funktion (om end implicit) i et WHERE-prædikat kan Oracle ikke bruge indekset på
A1.ID
kolonne.
For at komme uden om det skal du gøre et af følgende:
-
Opret et funktionsbaseret indeks på
A1.ID
kolonne:CREATE INDEX people_idx5 ON people (TO_CHAR(id));
-
Hvis du har brug for at matche poster på de første 3 tegn i ID-kolonnen, skal du oprette en anden kolonne af typen NUMBER, der kun indeholder disse 3 tegn og bruge en almindelig = operatør på den.
-
Opret en separat kolonne
ID_CHAR
af typenVARCHAR2
og udfyld den medTO_CHAR(id)
. Indekser det og brug i stedet forID
i dinWHERE
tilstand.Hvis du vælger at oprette en ekstra kolonne baseret på eksisterende ID-kolonne, skal du selvfølgelig holde disse 2 synkroniserede. Du kan gøre det i batch som en enkelt OPDATERING eller i en ON-UPDATE-udløser eller tilføje den kolonne til den relevante INSERT og UPDATE sætninger i din kode.