sql >> Database teknologi >  >> RDS >> Mysql

mysql:meget simpelt SELECT id ORDER BY LIMIT vil ikke bruge INDEX som forventet (?!)

Indeksopslag er efter værdi , ikke efter position . Et indeks kan søge efter en værdi 2955900, men det beder du ikke om. Du beder om, at forespørgslen starter ved en forskydning af rækken 2955900 i tabellen.

Optimeringsværktøjet kan ikke antage, at alle primære nøgleværdier er fortløbende. Så det er ret sandsynligt, at række nr. 2955900 har en meget højere værdi end det.

Selvom de primære nøgleværdier er fortløbende, har du muligvis en WHERE-betingelse, der kun matcher f.eks. 45 % af rækkerne. I så fald vil id-værdien på række nr. 2955900 være vej forbi id-værdien 2955900.

Med andre ord vil et indeksopslag af id-værdien 2955900 ikke levere rækken 2955900.

Så MySQL kan ikke bruge indekset til en grænseforskydning. Det skal scan rækkerne for at tælle dem, indtil den når offset+limit rækker.

MySQL har optimeringer relateret til LIMIT , men det handler mere om at stoppe en tabelscanning, når den har nået antallet af rækker, der skal returneres. Optimeringsværktøjet rapporterer muligvis stadig i en EXPLAIN-plan, at den forventer, at den kan skal scanne hele tabellen.

En hyppig misforståelse om FORCE INDEX er, at det tvinger brugen af ​​et indeks. :-) Faktisk, hvis forespørgslen ikke kan brug et indeks (eller hvis de tilgængelige indekser ikke har nogen fordel for denne forespørgsel), har FORCE INDEX ingen effekt.

Om din kommentar:

Sideinddeling er et hyppigt udbud af datadrevne webapplikationer. På trods af hvor almindelig denne funktion er, er den ikke let at optimere. Her er et par tips:

  • Hvorfor forespørger du med offset 2955900? Forventer du virkelig, at brugerne gennemskuer så mange sider? De fleste brugere giver op efter et par sider (nøjagtig hvor mange afhænger af applikationstypen og dataene).

  • Reducer antallet af forespørgsler. Din pagineringsfunktion kunne hente de første 5-10 sider, selvom den kun viser den første side til brugeren. Cache de andre sider, med den antagelse, at brugeren vil gå gennem et par sider. Kun hvis de går forbi det cachelagrede sæt sider, skal din app foretage en ny forespørgsel. Du kan endda cache alle 10 sider i Javascript i klientens browser, så klik på "Næste" er øjeblikkeligt for dem (i hvert fald for de første par sider).

  • Sæt ikke en "Sidste" knap på nogen brugergrænseflade, fordi folk vil klikke på den af ​​nysgerrighed. Bemærk, at Google har en "Næste"-knap, men ikke en "Sidste"-knap. Så selve brugergrænsefladen afskrækker folk fra at køre ineffektive forespørgsler med høje forskydninger.

  • Hvis brugeren går frem én side ad gangen, skal du bruge den højeste id-værdi, der blev returneret på den foregående side i WHERE-sætningen i den næste sides forespørgsel. dvs. følgende gør brug indekset, selv uden FORCE INDEX-tip:

    SELECT * FROM thistable WHERE id > 544 LIMIT 20
    



  1. Understøtter MySQL brugerdefinerede datatyper

  2. Hvordan bruger man Oracle ORDER BY og ROWNUM korrekt?

  3. Sådan sammenlignes arrays i PostgreSQL

  4. Hvad er formålet med $CONDITIONS under --query?