LIKE voorwaarde voor patroonovereenkomst verwacht karaktertypen te zien als zowel linker- als rechteroperanden. Wanneer het een NUMBER tegenkomt, wordt het impliciet geconverteerd naar char. Uw Query 1 is in feite stilzwijgend herschreven naar dit:
SELECT a1.*
FROM people a1
WHERE TO_CHAR(a1.id) LIKE '119%'
AND ROWNUM < 5
Dat gebeurt in jouw geval, en dat is om 2 redenen slecht:
- De conversie wordt uitgevoerd voor elke rij, wat traag is;
- Vanwege een functie (hoewel impliciet) in een WHERE-predikaat, kan Oracle de index op
A1.ID
niet gebruiken kolom.
Om het te omzeilen, moet je een van de volgende dingen doen:
-
Maak een functiegebaseerde index op
A1.ID
kolom:CREATE INDEX people_idx5 ON people (TO_CHAR(id));
-
Als u records wilt matchen op de eerste 3 tekens van de ID-kolom, maakt u een andere kolom van het type NUMBER die alleen deze 3 tekens bevat en gebruikt u een gewone = operator erop.
-
Maak een aparte kolom
ID_CHAR
van het typeVARCHAR2
en vul het metTO_CHAR(id)
. Indexeer het en gebruik in plaats vanID
in jeWHERE
staat.Als u ervoor kiest om een extra kolom te maken op basis van de bestaande ID-kolom, moet u deze 2 natuurlijk gesynchroniseerd houden. U kunt dat in batch doen als een enkele UPDATE, of in een ON-UPDATE-trigger, of die kolom toevoegen aan de juiste INSERT- en UPDATE-instructies in uw code.