sql >> Database >  >> RDS >> Mysql

MySQL-query's optimaliseren met zware joins

Uw gegevens zijn slecht geclusterd .

InnoDB zal rijen met "dichte" PK's fysiek dicht bij elkaar opslaan. Aangezien uw onderliggende tabellen surrogaat-PK's gebruiken, worden hun rijen willekeurig opgeslagen. Als het tijd is om berekeningen te maken voor de gegeven rij in de "master"-tabel, moet DBMS overal heen springen om de gerelateerde rijen uit de onderliggende tabellen te verzamelen.

Probeer in plaats van surrogaatsleutels meer "natuurlijke" sleutels te gebruiken, met de PK van de ouder voorop, vergelijkbaar met dit:

score_adjustments:
    entry_id: INT(11), FOREIGN KEY (entries.id)
    created: DATETIME
    amount: INT(4)
    PRIMARY KEY (entry_id, created)

rating_adjustments:
    entry_id: INT(11), FOREIGN KEY (entries.id)
    rating_no: INT(11)
    rating: DOUBLE
    PRIMARY KEY (entry_id, rating_no)

OPMERKING:Dit veronderstelt created 's resolutie is goed genoeg en de rating_no is toegevoegd om meerdere beoordelingen per entry_id toe te staan . Dit is slechts een voorbeeld - u kunt de PK's aanpassen aan uw behoeften.

Hiermee worden rijen die bij dezelfde entry_id horen "geforceerd". fysiek dicht bij elkaar worden opgeslagen, zodat een SUM of AVG kan worden berekend door slechts een bereikscan op de PK/clusteringsleutel en met zeer weinig I/O's.

Als alternatief (bijv. als u MyISAM gebruikt dat clustering niet ondersteunt), omslag de query met indexen zodat de onderliggende tabellen helemaal niet worden aangeraakt tijdens het zoeken.

Bovendien zou je je ontwerp kunnen denormaliseren en de huidige resultaten in de bovenliggende tabel kunnen cachen:

  • Bewaar SUM(score_adjustments.amount) als een fysiek veld en pas het aan via triggers telkens wanneer een rij wordt ingevoegd, bijgewerkt of verwijderd uit score_adjustments .
  • Bewaar SUM(rating_adjustments.rating) als "S" en COUNT(rating_aanpassingen.rating) als "C". Wanneer een rij wordt toegevoegd aan rating_adjustments , voeg het toe aan S en verhoog C. Bereken S/C tijdens runtime om het gemiddelde te krijgen. Verwerk updates en verwijderingen op dezelfde manier.


  1. Voortijdig einde van gegevensfout met PHP

  2. Geautomatiseerde of regelmatige back-up van mysql-gegevens

  3. SQL MIN- en MAX-resultaten met toegevoegde DISTINCT-operator in MySQL

  4. niet hoofdlettergevoelige zoekopdracht in mysql