0
votes

Impossible d'améliorer la vitesse de jointure SQL avec des index

Je suis totalement nouveau à SQL et j'essaie d'accélérer les requêtes de jointure pour de très grandes données. J'ai commencé à ajouter des index (mais pour être honnête, je n'ai pas de bien comprendre d'eux) et je ne vois pas beaucoup de changement, j'ai décidé de comparer un exemple plus simple et simulé. J'utilise l'interface PSQL de PostgreSQL 11.5 sur MacOS 10.14.6. Le serveur de données est hébergé localement sur mon ordinateur. Je m'excuse de tout manque d'informations pertinentes, première publication sur SQL.

Structures des bases de données h3>

J'ai créé deux bases de données initialement identiques, DB et DB_IDX. Je n'ai jamais mis d'index ni de clé sur des tables dans dB, tandis que j'essaie de mettre des index et des clés sur des tables dans db_idx. Je fais ensuite exécuter des requêtes de joints simples dans dB et db_idx séparément et je comparais les performances. Spécifiquement, db_idx est composé de deux tables: p>

  • une table client avec 100 000 rangées et la structure suivante: li> ul> xxx pré>
    • une table client_additional avec 70 000 lignes et la structure suivante: li> ul> xxx pré>

      La colonne client_id dans la table Client_Additional contient un sous-ensemble de valeurs client_id de client. Notez les touches principales et l'autre index que j'ai créé sur client_Additional. Je pensais que ceux-ci augmenteraient la vitesse de la requête de référence (voir ci-dessous) mais ce n'est pas le cas. P>

      de manière importante la base de données DB est exactement le même em> (même la même valeur) Sauf que cela a aucun index ni clé em>. strong> p>

      Note latérale: strong> La table client et client doit peut-être être une seule table, car Ils donnent des informations exactement au même niveau (niveau client). Cependant, la base de données que j'utilise dans la vie réelle a été structurée de cette manière: certaines tables sont divisées en plusieurs tables par "sujet" bien qu'elles donnent des informations au même niveau. Je ne sais pas si cela compte pour mon problème. P>

      Query de référence h3>

      J'utilise la requête suivante, qui imite beaucoup ce que je dois faire avec des données réelles:

          SELECT 
            client_additional.client_id, 
            client_additional.client_age,
            client.client_name
          FROM client
          INNER JOIN client_additional 
          ON client.client_id = client_additional.client_id;
      


0 commentaires

3 Réponses :


0
votes

Vous avez une clé primaire sur les deux tables qui seront utilisées pour le rejoindre s. Si vous souhaitez vraiment voir les requêtes ralentissez, retirez les touches primaires.

Qu'est-ce qui se passe? Eh bien, je suppose que les plans d'exécution sont les mêmes avec ou sans les indices secondaires. Vous auriez besoin de regarder les plans eux-mêmes.

Contrairement à la plupart des autres bases de données, Postgres ne bénéficie pas d'index de couverture, car les informations de verrouillage sont stockées uniquement dans les pages de données. Donc, les pages de données doivent toujours être consultées.


1 commentaires

Merci. Mais il n'ya absolument aucune clé primaire dans la base de données DB et la jointure prend la même heure que dans db_idx, qui a des clés primaires.



1
votes

Utilisez le verbe Expliquer pour voir comment le moteur SQL a l'intention de résoudre la requête. (Différents moteurs SQL présentent cela de différentes manières.) Vous pouvez voir de manière concluante si l'index sera utilisé.

En outre, vous devez d'abord charger les tables avec un lot de données de test, car expliquer vous indiquera ce que le moteur SQL a l'intention de faire En ce moment, et cette décision est basée en partie sur la taille de la table et diverses autres statistiques. Si la table est pratiquement vide, le moteur SQL peut décider que l'index ne serait pas utile maintenant.

Les moteurs SQL utilisent toutes sortes de trucs très intelligents pour optimiser les performances. Il est donc assez difficile d'obtenir un test de synchronisation utile. Mais, si expliquer vous dit que l'index est utilisé, c'est à peu près la réponse que vous recherchez.


2 commentaires

Merci. Lorsque vous dites beaucoup de données, de nombreuses lignes suffiraient-elles (10 millions?)? Ou dépend-il de la largeur des tables aussi?


J'ai vérifié les plans de requête et, en effet, la requête utilise uniquement des analyses séquentielles. J'ai réussi à faire utiliser l'index (clé primaire) en ajoutant une clause où la clause client_id. Dans l'ensemble, je veux juste m'assurer que je donne à SQL la possibilité d'être aussi rapide que possible. Mon vrai problème est extrêmement similaire: je dois rejoindre des tables sur leurs colonnes de clé primaire (même des deux côtés). Tout conseil conclu?



0
votes

Configuration d'un petit test DB, ajoutant des lignes et exécutant votre requête:

Merge Join  (cost=1.04..5388.45 rows=70000 width=13) (actual time=0.050..415.50
3 rows=70000 loops=1)
   Merge Cond: (client.client_id = client_additional.client_id)
   ->  Index Scan using client_pkey on client  (cost=0.42..6289.42 rows=200000 width=9) (actual time=0.022..86.897 rows=70001 loops=1)
   ->  Index Scan using client_additional_pkey on client_additional  (cost=0.29..2139.29 rows=70000 width=8) (actual time=0.016..86.818 rows=70000 loops=1)
 Planning Time: 0.517 ms
 Execution Time: 484.264 ms


0 commentaires