Zie Hoe MySQL indexen gebruikt .
Controleer ook of MySQL nog steeds een volledige tabelscanuser_metrics
tafel. In kleine tabellen is access-by-index eigenlijk duurder (I/O-gewijs) dan een tabelscan, en MySQL's optimizer houdt hier mogelijk rekening mee.
In tegenstelling tot mijn vorige bericht , blijkt dat MySQL ook gebruikt met een op kosten gebaseerde optimalisatie
, wat heel goed nieuws is - dat wil zeggen, op voorwaarde dat u uw ANALYZE
. uitvoert minstens één keer wanneer u denkt dat de hoeveelheid gegevens in uw database representatief is van toekomstig dagelijks gebruik.
Als u werkt met op kosten gebaseerde optimalisatieprogramma's (Oracle, Postgres, enz.), moet u ervoor zorgen dat u regelmatig ANALYZE
op uw verschillende tafels, aangezien hun grootte met meer dan 10-15% toeneemt. (Postgres doet dit standaard automatisch voor u, terwijl andere RDBMS'en deze verantwoordelijkheid overlaten aan een DBA, d.w.z. u.) Door middel van statistische analyse, ANALYZE
zal de optimizer helpen een beter idee te krijgen van hoeveel I/O (en andere bijbehorende bronnen, zoals CPU, bijvoorbeeld nodig voor sorteren) zal worden gebruikt bij het kiezen tussen verschillende uitvoeringsplannen voor kandidaten. Kan ANALYZE
niet uitvoeren kan resulteren in zeer slechte, soms rampzalige planningsbeslissingen (bijv. milliseconde-query's die soms uren duren vanwege slecht geneste lussen op JOIN
s.)
Als de prestaties nog steeds onvoldoende zijn na het uitvoeren van ANALYZE
, dan kunt u het probleem meestal omzeilen door hints te gebruiken, b.v. FORCE INDEX
, terwijl u in andere gevallen misschien bent gestruikeld over een MySQL-bug (bijv. deze oudere , die u had kunnen bijten als u Rails' nested_set
. zou gebruiken ).
Nu, omdat je in een Rails-app zit , zal het omslachtig zijn (en het doel van ActiveRecord
teniet doen) ) om uw aangepaste zoekopdrachten met hints te geven in plaats van door te gaan met het gebruiken van het ActiveRecord
-gegenereerde.
Ik had dat vermeld in onze Rails-applicatie alles SELECT
query's daalden tot onder 100 ms na het overschakelen naar Postgres, terwijl sommige van de complexe joins die werden gegenereerd door ActiveRecord
zou af en toe wel 15 seconden of meer in beslag nemen met MySQL 5.1 vanwege geneste lussen met binnenste tabelscans, zelfs als er indices beschikbaar waren. Geen enkele optimizer is perfect en u moet op de hoogte zijn van de opties. Andere potentiële prestatieproblemen waarmee u rekening moet houden, naast de optimalisatie van het queryplan, zijn vergrendeling. Dit valt echter buiten het bereik van uw probleem.