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 DISTINCT
est 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)?
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.
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;
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).