sql >> Database >  >> RDS >> Mysql

Hoe zorg ik ervoor dat MySQL een INDEX gebruikt voor weergavequery's?

Hoe zorg je ervoor dat MySQL een index gebruikt voor een weergavequery? Het korte antwoord, geef een index die MySQL kan gebruiken.

In dit geval is de optimale index waarschijnlijk een "dekkende" index:

... ON highscores (player, happened_in, score)

Het is waarschijnlijk dat MySQL die index zal gebruiken, en de EXPLAIN zal tonen:"Using index" vanwege de WHERE player = 24 (een gelijkheidspredikaat op de eerste kolom in de index. De GROUP BY happened_id (de tweede kolom in de index), kan MySQL dat optimaliseren met behulp van de index om een ​​sorteerbewerking te voorkomen. Inclusief de score kolom in de index zal het mogelijk maken om de zoekopdracht volledig uit de index te halen, zonder de gegevenspagina's waarnaar door de index wordt verwezen te hoeven bezoeken (op te zoeken).

Dat is het snelle antwoord. Het langere antwoord is dat het zeer onwaarschijnlijk is dat MySQL een index gebruikt met een leidende kolom van happened_id voor de weergavequery.

Waarom de weergave een prestatieprobleem veroorzaakt

Een van de problemen die u ondervindt met de MySQL-weergave is dat MySQL het predikaat niet van de buitenste query naar beneden in de weergavequery 'pusht'.

Uw buitenste zoekopdracht specificeert WHERE happened_in = 2006 . De MySQL-optimizer houdt geen rekening met het predikaat wanneer de interne "view-query" wordt uitgevoerd. Die query voor de weergave wordt afzonderlijk uitgevoerd, vóór de buitenste query. De resultatenset van de uitvoering van die query wordt "gematerialiseerd"; dat wil zeggen, de resultaten worden opgeslagen als een tussentijdse MyISAM-tabel. (MySQL noemt het een "afgeleide tabel", en die naam die ze gebruiken is logisch, als je de bewerkingen begrijpt die MysQL uitvoert.)

Het komt erop neer dat de index die u heeft gedefinieerd op happened_in wordt niet gebruikt door MySQL wanneer het de query uitvoert die de weergavedefinitie vormt.

Nadat de tussenliggende "afgeleide tabel" is gemaakt, DAN wordt de buitenste query uitgevoerd, waarbij die "afgeleide tabel" als een rijbron wordt gebruikt. Het is wanneer die buitenste query wordt uitgevoerd dat de happened_in = 2006 predikaat wordt geëvalueerd.

Merk op dat alle rijen van de view-query worden opgeslagen, wat (in jouw geval) een rij is voor ELKE waarde van happened_in , niet alleen degene waarvoor u een gelijkheidspredikaat opgeeft in de buitenste query.

De manier waarop view-query's worden verwerkt, kan door sommigen "onverwacht" zijn, en dit is een reden dat het gebruik van "views" in MySQL tot prestatieproblemen kan leiden, in vergelijking met de manier waarop view-query's worden verwerkt door andere relationele databases.

De prestaties van de view-query verbeteren met een geschikte dekkende index

Gezien uw weergavedefinitie en uw zoekopdracht, zou de toegangsmethode "Index gebruiken" voor de weergavequery ongeveer het beste zijn. Om dat te krijgen, heb je een dekkingsindex nodig, bijvoorbeeld

... ON highscores (player, happened_in, score).

Dat is waarschijnlijk de meest gunstige index (qua prestaties) voor uw bestaande weergavedefinitie en uw bestaande query. De player column is de leidende kolom omdat u een gelijkheidspredikaat voor die kolom in de viewquery hebt. De happened_in kolom is de volgende, omdat je een GROUP BY-bewerking op die kolom hebt, en MySQL zal deze index kunnen gebruiken om de GROUP BY-bewerking te optimaliseren. We nemen ook de score op kolom, omdat dat de enige andere kolom is waarnaar in uw zoekopdracht wordt verwezen. Dat maakt de index tot een "bedekkende" index, omdat MySQL aan die vraag rechtstreeks vanaf indexpagina's kan voldoen, zonder dat u pagina's in de onderliggende tabel hoeft te bezoeken. En dat is zo goed als we gaan uit van dat queryplan:"Index gebruiken" zonder "Bestandssortering gebruiken".

Prestaties vergelijken met zelfstandige zoekopdrachten zonder afgeleide tabel

U kunt het uitvoeringsplan voor uw zoekopdracht vergelijken met de weergave versus een gelijkwaardige zelfstandige zoekopdracht:

SELECT player
     , MAX(score) AS highest_score
     , happened_in
 FROM highscores
WHERE player = 24
  AND happened_in = 2006
GROUP
   BY player
    , happened_in

De zelfstandige zoekopdracht kan ook gebruik maken van een dekkende index, b.v.

... ON highscores (player, happened_in, score)

maar zonder de noodzaak om een ​​tussentijdse MyISAM-tabel te materialiseren.

Ik weet niet zeker of een van de voorgaande een direct antwoord geeft op de vraag die je stelde.

V:Hoe zorg ik ervoor dat MySQL een INDEX gebruikt voor weergavequery's?

A:Definieer een geschikte INDEX die de weergavequery kan gebruiken.

Het korte antwoord is:geef een "bedekkende index" (index bevat alle kolommen waarnaar in de view-query wordt verwezen). De leidende kolommen in die index moeten de kolommen zijn waarnaar wordt verwezen met gelijkheidspredikaten (in uw geval de kolom player zou een leidende kolom zijn omdat je een player = 24 . hebt predikaat in de query. Ook moeten de kolommen waarnaar in de GROUP BY wordt verwezen, leidende kolommen in de index zijn, waardoor MySQL de GROUP BY kan optimaliseren bewerking, door gebruik te maken van de index in plaats van een sorteerbewerking.

Het belangrijkste punt hier is dat de view-query in feite een op zichzelf staande query is; de resultaten van die query worden opgeslagen in een tussenliggende "afgeleide" tabel (een MyISAM-tabel die wordt gemaakt wanneer een query tegen de weergave wordt uitgevoerd.

Het gebruik van weergaven in MySQL is niet per se een "slecht idee", maar ik zou degenen die ervoor kiezen om weergaven binnen MySQL te gebruiken, sterk waarschuwen om zich ervan bewust te zijn hoe MySQL query's verwerkt die naar die weergaven verwijzen. En de manier waarop MySQL view-query's verwerkt, verschilt (aanzienlijk) van de manier waarop view-query's worden afgehandeld door andere databases (bijv. Oracle, SQL Server).



  1. postgresql:gegevenstype voor md5-berichtoverzicht?

  2. Selecteer de eerste rij in elke GROUP BY-groep?

  3. Kunnen database-items die zijn toegevoegd uit items worden verwijderd met de knop?

  4. Berekening van het aantal volledige maanden tussen twee datums in SQL