Il n'est pas recommandĂ© d'utiliser OFFSET et LIMIT dans les requĂȘtes de pagination

Les jours oĂč l'on pouvait ignorer l'optimisation des performances des bases de donnĂ©es sont rĂ©volus. Le temps ne s'arrĂȘte pas. Chaque nouvel entrepreneur du secteur technologique souhaite crĂ©er le prochain Facebook, cherchant Ă  collecter toutes les donnĂ©es Ă  sa portĂ©e. Ces donnĂ©es sont nĂ©cessaires aux entreprises pour former des modĂšles de meilleure qualitĂ©, qui aident Ă  gĂ©nĂ©rer des revenus. Dans de telles conditions, les programmeurs doivent crĂ©er des API qui permettent de travailler rapidement et efficacement avec d'Ă©normes volumes d'informations.

Il n'est pas recommandĂ© d'utiliser OFFSET et LIMIT dans les requĂȘtes de pagination

Si vous concevez des parties serveur d'applications ou des bases de donnĂ©es depuis un certain temps, vous avez probablement Ă©crit du code pour exĂ©cuter des requĂȘtes avec pagination. Par exemple, comme ceci :

SELECT * FROM table_name LIMIT 10 OFFSET 40

Est-ce bien le cas ?

Mais si vous avez effectué la pagination de cette maniÚre, je dois vous signaler avec regret que vous ne l'avez pas fait de maniÚre trÚs efficace.

Voulez-vous me contredire ? Vous pouvez ne perdre du temps. Slack, Shopify et Mixmax applique déjà des techniques que je souhaite vous présenter aujourd'hui.

Nommez un dĂ©veloppeur de backend qui n'a jamais utilisĂ© OFFSET et LIMIT pour exĂ©cuter des requĂȘtes avec pagination. Dans un MVP (produit minimum viable) et dans des projets oĂč de petites quantitĂ©s de donnĂ©es sont utilisĂ©es, cette approche est tout Ă  fait applicable. Elle fonctionne, pour ainsi dire, simplement.

Mais si vous devez crĂ©er des systĂšmes fiables et efficaces Ă  partir de zĂ©ro, il est nĂ©cessaire de se soucier de l'efficacitĂ© des requĂȘtes aux bases de donnĂ©es utilisĂ©es dans ces systĂšmes.

Aujourd'hui, nous allons parler des problĂšmes liĂ©s aux implĂ©mentations largement utilisĂ©es (dommage que ce soit le cas) des mĂ©canismes d'exĂ©cution des requĂȘtes avec pagination, et de la maniĂšre d'atteindre de hautes performances lors de l'exĂ©cution de telles requĂȘtes.

Qu'est-ce qui ne va pas avec OFFSET et LIMIT ?

Comme dĂ©jĂ  mentionnĂ©, OFFSET et LIMIT ils fonctionnent bien dans des projets oĂč il n'est pas nĂ©cessaire de traiter de gros volumes de donnĂ©es.

Le problĂšme survient lorsque la base de donnĂ©es s'agrandit au point de ne plus tenir en mĂ©moire serveur. Cependant, il est nĂ©cessaire d'utiliser des requĂȘtes avec pagination lors du travail avec cette base de donnĂ©es.

Pour que ce problĂšme se manifeste, il faut qu'il y ait une situation oĂč la SGBD recourt Ă  une opĂ©ration inefficace de scan complet de la table (Full Table Scan) lors de l'exĂ©cution de chaque requĂȘte avec pagination (pendant ce temps, des opĂ©rations d'insertion et de suppression de donnĂ©es peuvent se produire, et nous n'avons pas besoin des donnĂ©es obsolĂštes !).

Qu'est-ce qu'un "scan complet de table" (ou "scan séquentiel de table", Sequential Scan) ? C'est une opération au cours de laquelle la SGBD lit séquentiellement chaque ligne de la table, c'est-à-dire les données qu'elle contient, et vérifie leur conformité à la condition donnée. On sait que ce type de scan de tables est le plus lent. En effet, lors de son exécution, il y a beaucoup d'opérations d'entrée/sortie impliquant le systÚme de disque du serveur. La situation est aggravée par les temps d'attente liés à la manipulation des données stockées sur les disques, et le fait que le transfert de données du disque vers la mémoire est une opération gourmande en ressources.

Par exemple, vous avez des enregistrements sur 100000000 d'utilisateurs, et vous exĂ©cutez une requĂȘte avec la structure OFFSET 50000000. Cela signifie que la SGBD devra charger tous ces enregistrements (qui ne nous sont mĂȘme pas nĂ©cessaires !), les placer en mĂ©moire, et ensuite prendre, supposons, 20 rĂ©sultats, comme mentionnĂ© dans LIMIT.

Disons que cela pourrait ressembler Ă  ceci : "sĂ©lectionner les lignes de 50000 Ă  50020 sur 100000". Autrement dit, le systĂšme pour exĂ©cuter la requĂȘte devra d'abord charger 50000 lignes. Vous voyez combien de travail inutile il devra faire ?

Si vous ne me croyez pas, regardez l'exemple que j'ai créé en utilisant les capacités de db-fiddle.com. 

Il n'est pas recommandĂ© d'utiliser OFFSET et LIMIT dans les requĂȘtes de pagination
Exemple sur db-fiddle.com

LĂ , Ă  gauche, dans le champ SchĂ©ma SQL, il y a un code qui insĂšre 100000 lignes dans la base de donnĂ©es, et Ă  droite, dans le champ RequĂȘte SQL, deux requĂȘtes sont montrĂ©es. La premiĂšre, lente, ressemble Ă  ceci :

SELECT *
FROM `docs`
LIMIT 10 OFFSET 85000;

Et la seconde, qui reprĂ©sente une solution efficace au mĂȘme problĂšme, est :

SELECT *
FROM `docs`
WHERE id > 85000
LIMIT 10;

Pour exĂ©cuter ces requĂȘtes, il suffit d'appuyer sur le bouton ExĂ©cution en haut de la page. En faisant cela, nous comparerons les informations sur le temps d'exĂ©cution des requĂȘtes. Il s'avĂšre qu'une requĂȘte inefficace nĂ©cessite au minimum 30 fois plus de temps qu'une autre (d'un exĂ©cution Ă  l'autre, ce temps varie, par exemple, le systĂšme peut indiquer que la premiĂšre requĂȘte a pris 37 ms, alors que la seconde a pris 1 ms).

Et si les données augmentent, cela ne fera qu'empirer (pour vous en convaincre, regardez mon exemple avec 10 millions de lignes).

Ce que nous venons de discuter devrait vous donner une certaine comprĂ©hension de la maniĂšre dont les requĂȘtes sont rĂ©ellement traitĂ©es dans les bases de donnĂ©es.

Gardez Ă  l'esprit que plus la valeur est Ă©levĂ©e, OFFSET plus le temps d'exĂ©cution de la requĂȘte sera long.

Que vaut-il mieux utiliser Ă  la place de la combinaison OFFSET et LIMIT?

Au lieu de la combinaison, OFFSET et LIMIT il vaut mieux utiliser une structure construite comme suit :

SELECT * FROM table_name WHERE id > 10 LIMIT 20

Ceci est l'exĂ©cution d'une requĂȘte paginĂ©e basĂ©e sur le curseur.

Au lieu de stocker localement les courants OFFSET et LIMIT et de les transmettre avec chaque requĂȘte, il faut conserver la derniĂšre clĂ© primaire obtenue (gĂ©nĂ©ralement, c'est IDDeep Speech LIMIT, ce qui aboutira Ă  des requĂȘtes ressemblant Ă  celle ci-dessus.

Pourquoi? La raison est que, en indiquant explicitement l'identifiant de la derniĂšre ligne lue, vous indiquez Ă  votre SGBD oĂč commencer la recherche des donnĂ©es nĂ©cessaires. De plus, la recherche sera effectuĂ©e efficacement grĂące Ă  l'utilisation de la clĂ©, le systĂšme n'aura pas Ă  se concentrer sur les lignes en dehors de la plage spĂ©cifiĂ©e.

Jetons un Ɠil Ă  la comparaison suivante des performances de diffĂ©rentes requĂȘtes. Voici une requĂȘte inefficace.

Il n'est pas recommandĂ© d'utiliser OFFSET et LIMIT dans les requĂȘtes de pagination
RequĂȘte lente

Et voici la version optimisĂ©e de cette requĂȘte.

Il n'est pas recommandĂ© d'utiliser OFFSET et LIMIT dans les requĂȘtes de pagination
RequĂȘte rapide

Les deux requĂȘtes renvoient exactement le mĂȘme volume de donnĂ©es. Mais la premiĂšre prend 12,80 secondes, alors que la seconde ne prend que 0,01 seconde. Ressentez-vous la diffĂ©rence?

ProblĂšmes possibles

Pour assurer le bon fonctionnement de la mĂ©thode de requĂȘte proposĂ©e, il est nĂ©cessaire que la table contienne une colonne (ou des colonnes) avec des index uniques et sĂ©quentiels, tels qu'un identifiant numĂ©rique. Dans certains cas spĂ©cifiques, cela peut dĂ©terminer le succĂšs de l'utilisation de telles requĂȘtes pour amĂ©liorer la rapiditĂ© de l'accĂšs Ă  la base de donnĂ©es.

Évidemment, lors de la construction des requĂȘtes, il faut tenir compte des spĂ©cificitĂ©s de l'architecture des tables et choisir les mĂ©canismes qui fonctionneront le mieux avec les tables existantes. Par exemple, si vous devez traiter de grandes quantitĂ©s de donnĂ©es liĂ©es dans les requĂȘtes, vous pourriez trouver cet article intĂ©ressant. cette article.

Si nous faisons face Ă  l'absence de clĂ© primaire, par exemple si nous avons une table avec une relation « plusieurs-Ă -plusieurs », alors une approche traditionnelle impliquant l'utilisation OFFSET et LIMIT, nous conviendra certainement. Cependant, son utilisation peut entraĂźner l'exĂ©cution de requĂȘtes potentiellement lentes. Dans de tels cas, je recommanderais d'utiliser une clĂ© primaire avec auto-incrĂ©ment, mĂȘme si elle est nĂ©cessaire uniquement pour organiser l'exĂ©cution de requĂȘtes paginĂ©es.

Si ce sujet vous intĂ©resse — voici, voici et voici — quelques ressources utiles.

Résultats

La principale conclusion que nous pouvons tirer est que, quelle que soit la taille des bases de donnĂ©es, il est toujours nĂ©cessaire d'analyser la vitesse d'exĂ©cution des requĂȘtes. De nos jours, l'Ă©volutivitĂ© des solutions est extrĂȘmement importante, et si, dĂšs le dĂ©but du dĂ©veloppement d'un systĂšme, tout est bien conçu, cela peut Ă  l'avenir Ă©viter Ă  un dĂ©veloppeur de nombreux problĂšmes.

Comment analysez-vous et optimisez-vous les requĂȘtes aux bases de donnĂ©es?

Il n'est pas recommandĂ© d'utiliser OFFSET et LIMIT dans les requĂȘtes de pagination

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster