sql >> Database >  >> RDS >> Mysql

Query's in een database optimaliseren - de basis

Je moet opzoeken voor elke waar-voorwaarde en voor elke verbinding ... op voorwaarde. De twee werken hetzelfde.

Stel dat we schrijven

select name
from customer
where customerid=37;

Op de een of andere manier moet het DBMS het record of de records met customerid=37 vinden. Als er geen index is, is de enige manier om dit te doen het lezen van elk record in de tabel, waarbij het klant-ID wordt vergeleken met 37. Zelfs als het er een vindt, kan het niet weten dat er maar één is, dus moet het blijven zoeken naar anderen.

Als u een index op klant-id maakt, heeft het DBMS manieren om de index zeer snel te doorzoeken. Het is geen sequentiële zoekopdracht, maar, afhankelijk van de database, een binaire zoekopdracht of een andere efficiënte methode. Hoe precies maakt niet uit, accepteer dat het veel sneller is dan sequentieel. De index brengt het vervolgens rechtstreeks naar de juiste record of records. Bovendien, als u specificeert dat de index "uniek" is, dan weet de database dat er maar één kan zijn, zodat het geen tijd verspilt aan het zoeken naar een tweede. (En het DBMS zal voorkomen dat u een tweede toevoegt.)

Overweeg nu deze vraag:

select name
from customer
where city='Albany' and state='NY';

Nu hebben we twee voorwaarden. Als u een index hebt op slechts één van die velden, zal het DBMS die index gebruiken om een ​​subset van de records te vinden en deze vervolgens opeenvolgend doorzoeken. Als u bijvoorbeeld een index op staat heeft, zal het DBMS snel het eerste record voor NY vinden, vervolgens achtereenvolgens zoeken naar city='Albany' en stoppen met zoeken wanneer het het laatste record voor NY bereikt.

Als u een index heeft die beide velden bevat, d.w.z. "creëer index op klant (staat, stad)", dan kan het DBMS onmiddellijk naar de juiste records zoomen.

Als u twee afzonderlijke indexen heeft, één voor elk veld, heeft het DBMS verschillende regels die van toepassing zijn om te beslissen welke index moet worden gebruikt. Nogmaals, hoe dit precies wordt gedaan, hangt af van het specifieke DBMS dat u gebruikt, maar in feite probeert het statistieken bij te houden over het totale aantal records, het aantal verschillende waarden en de verdeling van waarden. Vervolgens doorzoekt het die records opeenvolgend voor degenen die aan de andere voorwaarde voldoen. In dit geval zou de DBMS waarschijnlijk vaststellen dat er veel meer steden zijn dan staten, dus door de stedenindex te gebruiken kan snel worden ingezoomd op de 'Albany'-records. Vervolgens zal het deze achtereenvolgens doorzoeken, waarbij de staat van elk wordt vergeleken met 'NY'. Als u records heeft voor Albany, Californië, worden deze overgeslagen.

Elke join vereist een soort van look-up.

Stel dat we schrijven

select customer.name
from transaction
join customer on transaction.customerid=customer.customerid
where transaction.transactiondate='2010-07-04' and customer.type='Q';

Nu moet het DBMS beslissen welke tabel het eerst moet worden gelezen, de juiste records van daaruit selecteren en vervolgens de overeenkomende records in de andere tabel zoeken.

Als u een index had op transaction.transactiondate en customer.customerid, zou het beste plan waarschijnlijk zijn om alle transacties met deze datum te vinden, en voor elk daarvan de klant te vinden met de overeenkomende klant-id, en vervolgens te verifiëren dat de klant het juiste type.

Als je geen index hebt op customer.customerid, dan kan het DBMS de transactie snel vinden, maar dan zou het voor elke transactie achtereenvolgens de klantentabel moeten doorzoeken op zoek naar een overeenkomend klant-ID. (Dit zou waarschijnlijk erg traag zijn.)

Stel in plaats daarvan dat de enige indexen die u heeft op transaction.customerid en customer.type staan. Dan zou het DBMS waarschijnlijk een heel ander plan gebruiken. Het zou waarschijnlijk de klantentabel scannen voor alle klanten met het juiste type, dan voor elk van deze alle transacties voor deze klant zoeken en ze achtereenvolgens zoeken naar de juiste datum.

De belangrijkste sleutel tot optimalisatie is om erachter te komen welke indexen echt helpen en die indexen te maken. Extra, ongebruikte indexen zijn een belasting voor de database omdat het veel werk kost om ze te onderhouden, en als ze nooit worden gebruikt, is dit verspilde moeite.

U kunt zien welke indexen het DBMS voor een bepaalde query zal gebruiken met de opdracht EXPLAIN. Ik gebruik dit de hele tijd om te bepalen of mijn zoekopdrachten goed worden geoptimaliseerd of dat ik extra indexen moet maken. (Lees de documentatie over deze opdracht voor een uitleg van de uitvoer.)

Waarschuwing:onthoud dat ik zei dat het DBMS statistieken bijhoudt over het aantal records en het aantal verschillende waarden enzovoort in elke tabel. EXPLAIN kan u vandaag een heel ander plan geven dan gisteren als de gegevens zijn gewijzigd. Als u bijvoorbeeld een query hebt die twee tabellen samenvoegt en een van deze tabellen is erg klein en de andere groot, zal de neiging hebben om eerst de kleine tabel te lezen en vervolgens overeenkomende records in de grote tabel te vinden. Het toevoegen van records aan een tabel kan veranderen welke groter is, en er dus toe leiden dat het DBMS zijn plan wijzigt. U moet dus proberen EXPLAINS te doen tegen een database met realistische gegevens. Rennen tegen een testdatabase met 5 records in elke tabel is van veel minder waarde dan tegen een live-database.

Nou, er valt nog veel meer te zeggen, maar ik wil hier geen boek schrijven.



  1. hoe dynamische json in treeview wpf te binden

  2. io.vertx.mysqlclient.MySQLPool.query ().execute wordt nooit echt uitgevoerd en geeft niets terug

  3. Is Markdown (met strip_tags) voldoende om XSS-aanvallen te stoppen?

  4. MySQL-opgeslagen procedure versus functie, welke zou ik wanneer gebruiken?