sql >> Database >  >> RDS >> Mysql

mysql:heel eenvoudig SELECT id ORDER BY LIMIT gebruikt INDEX niet zoals verwacht (?!)

Indexzoekopdrachten zijn op waarde , niet op positie . Een index kan zoeken naar een waarde 2955900, maar daar vraag je niet om. U vraagt ​​om de zoekopdracht te starten op een offset van de 2955900ste rij in de tabel.

Het optimalisatieprogramma kan er niet vanuit gaan dat alle primaire sleutelwaarden opeenvolgend zijn. Het is dus vrij waarschijnlijk dat de 2955900ste rij een veel hogere waarde heeft.

Zelfs als de primaire sleutelwaarden opeenvolgend zijn, kunt u een WHERE-voorwaarde hebben die bijvoorbeeld slechts overeenkomt met 45% van de rijen. In dat geval zou de id-waarde op de 2955900ste rij way . zijn voorbij de ID-waarde 2955900.

Met andere woorden, een index-lookup van de id-waarde 2955900 levert niet de 2955900e rij op.

Dus MySQL kan de index niet gebruiken voor de offset van een limiet. Het moet scan de rijen om ze te tellen totdat het offset+limietrijen bereikt.

MySQL heeft wel optimalisaties gerelateerd aan LIMIT , maar het gaat meer om het stoppen van een tabelscan zodra deze het aantal te retourneren rijen heeft bereikt. De optimizer kan nog steeds in een EXPLAIN-plan melden dat hij verwacht dat het misschien moet de hele tafel scannen.

Een veel voorkomend misverstand over FORCE INDEX is dat het het gebruik van een index dwingt. :-)In feite, als de zoekopdracht niet kan gebruik een index (of als de beschikbare indexen geen voordeel hebben voor deze zoekopdracht), heeft FORCE INDEX geen effect.

Opnieuw uw opmerking:

Paginering is een veel voorkomende vloek van datagestuurde webapplicaties. Ondanks hoe vaak deze functie voorkomt, is het niet eenvoudig te optimaliseren. Hier zijn een paar tips:

  • Waarom vraag je met offset 2955900? Verwacht je echt dat gebruikers door zoveel pagina's bladeren? De meeste gebruikers geven het na een paar pagina's op (het exacte aantal hangt af van het type applicatie en de gegevens).

  • Verminder het aantal zoekopdrachten. Uw pagineringsfunctie kan de eerste 5-10 pagina's ophalen, zelfs als alleen de eerste pagina aan de gebruiker wordt getoond. Cache de andere pagina's, in de veronderstelling dat de gebruiker door een paar pagina's zal gaan. Alleen als ze voorbij de in de cache opgeslagen reeks pagina's komen, hoeft uw app nog een zoekopdracht uit te voeren. Je zou zelfs alle 10 pagina's in Javascript in de browser van de klant kunnen cachen, dus klikken op "Volgende" is onmiddellijk voor hen (tenminste voor die eerste paar pagina's).

  • Plaats geen "Laatste" knop op een gebruikersinterface, omdat mensen erop zullen klikken uit nieuwsgierigheid. Merk op dat Google een knop 'Volgende' heeft, maar geen knop 'Laatste'. Dus de gebruikersinterface ontmoedigt mensen zelf om inefficiënte zoekopdrachten met hoge offsets uit te voeren.

  • Als de gebruiker één pagina tegelijk vooruitgaat, gebruikt u de hoogste id-waarde die op de vorige pagina is geretourneerd in de WHERE-component van de zoekopdracht van de volgende pagina. D.w.z. het volgende doet gebruik de index, zelfs zonder FORCE INDEX hint:

    SELECT * FROM thistable WHERE id > 544 LIMIT 20
    



  1. Hoe kan ik alle tabellen in MySQL vinden met specifieke kolomnamen erin?

  2. SQL om een ​​samengevoegde reeks resultaten te retourneren

  3. Dieper graven in Django-migraties

  4. to_date functie met sysdate