De meeste bedrijfsdatabases, waaronder Oracle, gebruiken een op kosten gebaseerde optimalisatieprogramma om het juiste queryplan voor een bepaalde SQL-instructie te bepalen. Dit betekent dat de optimizer informatie over de gegevens gebruikt om te bepalen hoe een query moet worden uitgevoerd in plaats van te vertrouwen op regels (dit is wat de oudere, op regels gebaseerde optimizer deed).
Stel je bijvoorbeeld een tabel voor voor een eenvoudige toepassing voor het opsporen van fouten
CREATE TABLE issues (
issue_id number primary key,
issue_text clob,
issue_status varchar2(10)
);
CREATE INDEX idx_issue_status
ON issues( issue_status );
Als ik een groot bedrijf ben, heb ik misschien 1 miljoen rijen in deze tabel. Daarvan hebben er 100 een issue_status
van ACTIVE, 10.000 hebben een issue_status
van WACHTRIJ en 989.900 hebben de status VOLTOOID. Als ik een query op de tabel wil uitvoeren om mijn actieve problemen te vinden
SELECT *
FROM issues
WHERE issue_status = 'ACTIVE'
de optimizer heeft een keuze. Het kan ofwel de index gebruiken op issue_status
en doe vervolgens een zoekopdracht in één rij in de tabel voor elke rij in de index die overeenkomt of het kan een tabelscan uitvoeren op de issues
tafel. Welk abonnement het meest efficiënt is, hangt af van de gegevens in de tabel. Als Oracle verwacht dat de query een klein deel van de gegevens in de tabel retourneert, zou het efficiënter zijn om de index te gebruiken. Als Oracle verwacht dat de query een aanzienlijk deel van de gegevens in de tabel retourneert, zou een tabelscan efficiënter zijn.
DBMS_STATS.GATHER_TABLE_STATS
is wat de statistieken verzamelt die Oracle in staat stellen deze beslissing te nemen. Het vertelt Oracle dat er ongeveer 1 miljoen rijen in de tabel zijn, dat er 3 verschillende waarden zijn voor de issue_status
kolom en dat de gegevens ongelijk verdeeld zijn. Oracle weet dus een index te gebruiken voor de query om alle actieve problemen te vinden. Maar het weet ook dat wanneer je je omdraait en probeert te zoeken naar alle gesloten problemen
SELECT *
FROM issues
WHERE issue_status = 'CLOSED'
dat het efficiënter is om een tabelscan uit te voeren.
Door statistieken te verzamelen, kunnen de queryplannen in de loop van de tijd veranderen naarmate de gegevensvolumes en gegevensdistributies veranderen. Wanneer u de issue tracker voor het eerst installeert, zult u zeer weinig VOLTOOIDE problemen hebben en meer ACTIEVE en IN DE WACHTRIJ GESTELDE problemen. Na verloop van tijd stijgt het aantal VOLTOOIDE problemen veel sneller. Naarmate u meer rijen in de tabel krijgt en de relatieve fractie van de rijen in de verschillende statussen verandert, veranderen de queryplannen zodat u in de ideale wereld altijd het meest efficiënte plan krijgt.