Schéma d'optimisation des requêtes de pagination MySQL pour un grand volume de données

Méthode 1: utilisez directement l'instruction SQL fournie par la base de données

Style de déclaration: dans  MySQL, les méthodes suivantes sont disponibles:

SELECT * FROM 表名称 LIMIT M,N

S'adapter à la scène:  convient aux situations avec une petite quantité de données (tuple cent / milliers)

Raisons / inconvénients:  analyse complète de la table, la vitesse sera très lente et certains jeux de résultats de base de données retournent instables (comme renvoyer 1, 2, 3 à la fois et renvoyer 2, 1, 3 à l'autre moment). La limite est limitée par rapport à l'ensemble de résultats Retirez la sortie N à la position M et jetez le reste.

 

Méthode 2: créer une clé primaire ou un index unique, utiliser l'index (en supposant 10 entrées par page)

Style de déclaration: dans  MySQL, les méthodes suivantes sont disponibles:

SELECT * FROM 表名称 WHERE id_pk > (pageNum*10) LIMIT M

Scénarios d'adaptation:  adaptés aux situations avec une grande quantité de données (dizaines de milliers de tuples)

Raison:  Balayage d'index, la vitesse sera très rapide. Un ami a suggéré: Parce que la requête de données n'est pas triée en fonction de pk_id, il y aura donc des cas de données manquantes, uniquement la méthode 3

 

Méthode 3: réorganiser en fonction de l'index

Style de déclaration: dans  MySQL, les méthodes suivantes sont disponibles:

SELECT * FROM 表名称 WHERE id_pk > (pageNum*10) ORDER BY id_pk ASC LIMIT M

Scénarios d'adaptation:  convient aux situations avec une grande quantité de données (des dizaines de milliers de tuples). Il est préférable que l'objet de colonne après ORDER BY soit la clé primaire ou unique, afin que l'opération ORDERBY puisse être éliminée par l'index mais que l'ensemble de résultats soit stable (signification stable , Voir méthode 1)

Raison: l'  analyse d'index sera très rapide, mais l'opération de tri de MySQL est seulement ASC sans DESC (DESC est faux, le vrai DESC sera fait dans le futur, attendons avec impatience ...).

 

Méthode 4: utiliser prepare en fonction de l'index

Le premier point d'interrogation signifie pageNum, le second? Indique le nombre de tuples par page

Style de déclaration: dans  MySQL, les méthodes suivantes sont disponibles:

PREPARE stmt_name FROM SELECT * FROM 表名称 WHERE id_pk > (?* ?) ORDER BY id_pk ASC LIMIT M

S'adapter à la scène:  gros volume de données

Raison:  Balayage d'index, la vitesse sera très rapide. L'instruction de préparation est un peu plus rapide que l'instruction de requête générale.

 

Méthode 5: l'utilisation de MySQL pour prendre en charge les opérations ORDER peut utiliser des index pour localiser rapidement certains tuples et éviter les analyses complètes de la table

Par exemple: lisez le tuple de la 1000e à la 1019e ligne (pk est la clé primaire / clé unique).

SELECT * FROM your_table WHERE pk>=1000 ORDER BY pk ASC LIMIT 0,20

Méthode 6: utilisez «sous-requête / jointure + index» pour localiser rapidement la position du tuple, puis lisez le tuple.

Par exemple (id est la clé primaire / clé unique, variable en police bleue)

Exemples d'utilisation de sous-requêtes:

SELECT * FROM your_table WHERE id <=
(SELECT id FROM your_table ORDER BY id desc LIMIT ($page-1)*$pagesize ORDER BY id desc
LIMIT $pagesize 

Utilisez l'exemple de connexion:

SELECT * FROM your_table AS t1
JOIN (SELECT id FROM your_table ORDER BY id desc LIMIT ($page-1)*$pagesize AS t2
WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize; 

MySQL utilise la pagination de limite pour un volume de données important. À mesure que le nombre de pages augmente, l'efficacité des requêtes diminue.

 

Expérience de test

1. Utilisez directement les instructions de pagination limit start et count, qui sont également les méthodes utilisées dans mon programme:

select * from product limit start, count 

Lorsque la page de démarrage est petite, la requête n'a pas de problèmes de performances. Regardons le temps d'exécution de la pagination de 10, 100, 1000, 10000 (20 entrées par page).

comme suit:

select * from product limit 10, 20   --0.016秒 
select * from product limit 100, 20  -- 0.016秒
select * from product limit 1000, 20  -- 0.047秒
select * from product limit 10000, 20   --0.094秒

Nous avons vu qu'à mesure que l'enregistrement de départ augmente, le temps augmente également. Cela montre que la limite de l'instruction de pagination a beaucoup à voir avec le numéro de page de départ. Ensuite, nous changeons l'enregistrement de départ en 40w et l'examinons (c'est-à-dire l'enregistrement En général)

select * from product limit 400000, 20   --3.229秒 

Regardez le moment où nous avons pris la dernière page de disques

select * from product limit 866613, 20   --37.44秒 

Évidemment, ce genre de temps est insupportable pour la plus grande page numérotée de ce type de pagination.

À partir de là, nous pouvons également résumer deux choses:

  • Le temps de requête de l'instruction de limite est proportionnel à la position de l'enregistrement de départ

  • L'instruction limit de mysql est très pratique, mais elle ne convient pas pour une utilisation directe pour les tables avec de nombreux enregistrements.

 

2. Méthode d'optimisation des performances pour les problèmes de pagination de limite

Utilisez l'index de couverture de la table pour accélérer les requêtes de pagination

Nous savons tous que si seule la colonne d'index (index de couverture) est incluse dans l'instruction qui utilise la requête d'index, la requête sera très rapide dans ce cas.

Comme il existe un algorithme optimisé pour la recherche d'index et que les données se trouvent sur l'index de requête, il n'est pas nécessaire de trouver l'adresse de données appropriée, ce qui permet de gagner beaucoup de temps. De plus, il existe des caches d'index connexes dans Mysql. Il est préférable d'utiliser le cache lorsque la concurrence est élevée.

Dans notre exemple, nous savons que le champ id est la clé primaire, il contient donc naturellement l'index de clé primaire par défaut. Examinons maintenant l'effet de la requête en utilisant l'index de couverture.

Cette fois, nous interrogeons les données de la dernière page (en utilisant l'index de couverture, qui ne contient que la colonne id), comme suit:

select id from product limit 866613, 20 0.2秒 

Comparé à 37,44 secondes pour interroger toutes les colonnes, c'est environ 100 fois plus rapide

Donc, si nous voulons interroger toutes les colonnes, il existe deux méthodes, l'une est sous la forme id> = et l'autre consiste à utiliser join. Regardez la situation réelle:

SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20

Le temps de requête est de 0,2 seconde!

 

Une autre façon d'écrire

SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id

Le temps de requête est également très court!

3. Méthode d'optimisation de l'indice composé

Quelle peut être la performance de MySql? MySql est définitivement une base de données adaptée aux maîtres de niveau dba. Généralement, vous pouvez écrire un petit système avec 10 000 articles de presse. Un développement rapide peut être réalisé avec le framework xx.

Mais la quantité de données a atteint 100 000, des millions à des dizaines de millions, sa performance peut-elle être aussi élevée? Une petite erreur peut entraîner la réécriture de l'ensemble du système, ou même le système ne peut pas fonctionner normalement! D'accord, pas tellement de bêtises.

 

Parlez avec des faits, voyez des exemples:

La table de données collectée (id, title, info, vtype) a ces 4 champs, où title utilise une longueur fixe, info utilise du texte, id est graduel, vtype est tinyint et vtype est index.

Il s'agit d'un modèle simple de système d'information de base. Maintenant, remplissez les données pour remplir 100 000 nouvelles. Enfin, la collecte est de 100 000 enregistrements, et la table de la base de données occupe un disque 1.6G.

OK, regardez l'instruction SQL suivante:

select id,title from collect limit 1000,10;

Bientôt; en gros, c'est OK en 0,01 seconde, puis regardez ce qui suit

select id,title from collect limit 90000,10;

La pagination commence à partir de 90 000, le résultat?

8-9 secondes pour terminer, quel est le problème avec mon dieu? En fait, pour optimiser ces données, trouvez la réponse en ligne. Regardez la déclaration suivante:

select id from collect order by id limit 90000,10;

Bientôt, 0,04 seconde sera OK. Pourquoi? Comme la clé primaire id est utilisée pour l'indexation, elle est bien sûr rapide.

La réforme en ligne est:

select id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10;

C'est le résultat de l'indexation avec id. Mais si le problème est un peu compliqué, c'est fini. Regardez la déclaration suivante

select id from collect where vtype=1 order by id limit 90000,10; 

Très lent, cela a pris 8 à 9 secondes!

Quand j'arriverai ici, je crois que beaucoup de gens se sentiront brisés! Le vtype est-il indexé? Comment cela peut-il être lent? L'index vtype est bon, vous directement

select id from collect where vtype=1 limit 1000,10;

Elle est très rapide, en gros 0,05 seconde, mais elle est multipliée par 90. À partir de 90 000, soit la vitesse de 0,05 * 90 = 4,5 secondes. Et le résultat du test a atteint un ordre de grandeur en 8-9 secondes.

 

De là, quelqu'un a avancé l'idée de sous-table, c'est la même idée que le forum dis #cuz. L'idée est la suivante:

Créez une table d'index: t (id, title, vtype) et définissez-la sur une longueur fixe, puis effectuez une pagination, puis les résultats seront paginés pour trouver des informations dans collect. Est-ce faisable? Sous l'expérience, vous saurez.

100 000 enregistrements sont stockés dans t (id, titre, vtype) et la taille de la table de données est d'environ 20M. utilisation

select id from t where vtype=1 order by id limit 90000,10;

bientôt. Fondamentalement, il peut fonctionner en 0,1-0,2 secondes. Pourquoi cela est-il ainsi?

Je suppose que c'est parce que les données collectées sont trop importantes, donc la pagination ira un long chemin. La limite est entièrement liée à la taille de la table de données. En fait, il s'agit toujours d'une analyse complète de la table, simplement parce que la quantité de données est petite, seulement 100 000 est rapide. OK, faisons une expérience folle, ajoutez 1 million pour tester les performances. Après avoir ajouté 10 fois les données, la table t a immédiatement atteint plus de 200M, et elle était de longueur fixe. Toujours l'instruction de requête à l'instant, le temps est de 0,1-0,2 secondes pour terminer! Pas de problème avec les performances sous-mètres?

faux! Parce que notre limite est toujours de 90 000, si vite. Donnez un gros, commencez à 900000

select id from t where vtype=1 order by id limit 900000,10;

Regardez le résultat, le temps est de 1-2 secondes! Pourquoi?

Il est encore si long après le sous-tableau, très déprimant! Certains disent que la longueur fixe améliorera les performances de la limite.Au début, je pensais que parce que la longueur d'un enregistrement est fixe, mysql devrait être capable de calculer la position de 900 000, non? Mais nous avons surestimé l'intelligence de mysql. Ce n'est pas une base de données commerciale. Il s'avère que les longueurs fixes et non fixes ont peu d'effet sur la limite? Pas étonnant que certains disent que discuz sera très lent après avoir atteint 1 million d'enregistrements. Je crois que c'est vrai. Ceci est lié à la conception de bases de données!

MySQL ne peut-il pas dépasser la limite d'un million? ? ? Est-ce vraiment la limite quand il atteint 1 million de pages?

La réponse est: pourquoi ne peut pas dépasser 1 million est dû au fait de ne pas concevoir mysql. Introduisons la méthode des tables non fractionnées, faisons un test fou! Une table gère 1 million d'enregistrements et une base de données 10G, comment paginer rapidement!

D'accord, notre test retourne à la table de collecte, et la conclusion du test est:

300 000 données, il est possible d'utiliser la méthode des sous-tableaux, et la vitesse de plus de 300 000 sera plus lente que vous ne pouvez la supporter! Bien sûr, si vous utilisez la méthode sub-table + me, c'est absolument parfait. Mais après avoir utilisé ma méthode, il peut être parfaitement résolu sans sous-table!

La réponse est: indice composé! Une fois lors de la conception d'un index mysql, j'ai découvert accidentellement que le nom de l'index peut être choisi à volonté et que plusieurs champs peuvent être sélectionnés.

Le début

select id from collect order by id limit 90000,10; 

C'est tellement rapide parce que l'index a disparu, mais si vous ajoutez où, l'index ne sera pas pris. J'ai ajouté un index comme search (vtype, id) avec l'idée d'essayer.

Puis testez

select id from collect where vtype=1 limit 90000,10; 

très vite! Terminé en 0,04 seconde!

Testez à nouveau:

select id ,title from collect where vtype=1 limit 90000,10; 

Malheureusement, 8-9 secondes, pas d'index de recherche!

Tester à nouveau: recherchez (id, vtype), ou sélectionnez id cette phrase, également très regrettable, 0,5 seconde.

Pour résumer: si vous avez des conditions where et que vous voulez utiliser la limite pour l'index, vous devez concevoir un index. Placez où en premier et la clé primaire utilisée par limite en second, et vous ne pouvez sélectionner que la clé primaire!

Le problème de pagination est parfaitement résolu. Si vous pouvez renvoyer l'identifiant rapidement, il est possible d'optimiser la limite. Selon cette logique, une limite de niveau d'un million doit être divisée en 0,0x seconde. Il semble que l'optimisation et l'indexation des instructions mysql soient très importantes!

 

Je suppose que tu aimes

Origine blog.csdn.net/bj_chengrong/article/details/103233267
conseillé
Classement