web-dev-qa-db-fra.com

Solution pour accélérer une requête SELECT DISTINCT lente dans Postgres

La requête est essentiellement:

SELECT DISTINCT "my_table"."foo" from "my_table" WHERE...

En prétendant que je suis certain à 100% que la partie DISTINCT de la requête est la raison pour laquelle elle s'exécute lentement, j'ai omis le reste de la requête pour éviter toute confusion, car c'est la lenteur de la partie distincte que je suis principalement concerné (distinct est toujours une source de lenteur).

Le tableau en question contient 2,5 millions de lignes de données. Le DISTINCTest nécessaire à des fins qui ne sont pas répertoriées ici (car je ne veux pas sauvegarder une requête modifiée, mais plutôt simplement des informations générales sur l'accélération de l'exécution de requêtes distinctes au DBMS niveau, si possible).

Comment puis-je faire fonctionner DISTINCT plus rapidement (en utilisant Postgres 9 en particulier) sans modifier le SQL (c'est-à-dire que je ne peux pas modifier ce SQL entrant, mais avoir accès pour optimiser quelque chose au niveau de la base de données)?

25
orokusaki

Votre DISTINCT le fait trier les lignes de sortie afin de trouver des doublons. Si vous placez un index sur les colonnes sélectionnées par la requête, la base de données peut être en mesure de les lire dans l'ordre d'index et d'enregistrer l'étape de tri. Beaucoup dépendra des détails de la requête et des tables impliquées - votre dire que vous "savez que le problème vient du DISTINCT" limite vraiment la portée des réponses disponibles.

15
antlersoft

Souvent, vous pouvez accélérer l'exécution de ces requêtes en contournant distinct en utilisant un group by au lieu:

select my_table.foo 
from my_table 
where [whatever where conditions you want]
group by foo;
28
user554546

Vous pouvez essayer d'augmenter le paramètre work_mem, en fonction de la taille de votre ensemble de données. Cela peut entraîner le basculement du plan de requête vers des agrégats de hachage, qui sont généralement plus rapides.

Mais avant de le placer trop haut dans le monde, lisez-le d'abord. Vous pouvez facilement faire exploser votre serveur, car le max_connections Le paramètre agit comme un multiplicateur de ce nombre.

Cela signifie que si vous définissez work_mem = 128MB et vous définissez max_connections = 100 (par défaut), vous devez disposer de plus de 12,8 Go de RAM. Vous dites essentiellement au serveur qu'il peut en utiliser autant pour effectuer des requêtes (sans même considérer toute autre utilisation de la mémoire par Postgres ou autre).

6
maniek