SELECT * FROM trips, dates WHERE places_number_on_flag > 0 AND places_number > 0 AND ( places_number - ( (SELECT Count(id) FROM resrv_customers WHERE trip = trips.id AND ow > 0) + (SELECT Count(id) FROM resrv_customers WHERE trip = trips.id AND extra_seat = 1 AND ow > 0) ) < 20 ) AND dates.id = trips.trip_date AND dates.from_date > 2458553; It returns 5 rows after about a minute and 50 seconds.I want it to be faster.
3 Réponses :
Nous pouvons essayer de réécrire votre requête à l'aide d'une jointure à la table code> resrv_customères code>, au lieu d'utiliser des sous-requêtes corrélées coûteuses: indexation ici pourrait être délicate, car Faites un SELECT * code>. Pour que Postgres utilise n'importe quel index, vous devrez peut-être faire beaucoup de colonnes couvrant, c'est-à-dire créer de grands indices. P> p>
Juste un commentaire sur l'optimisation, ce CTE sera probablement un goulot d'étranglement probablement le processus, car il aura besoin de grouper et de compter tout le tableau resrv_customères code>, lorsque vous n'avez besoin que de correspondre au "code> trip.id code>. Aussi
ow> 0 code> pourrait être dans la clause WHERE, puisque les deux comptes le nécessitent, plus en utilisant la clause
Filtre Code> ( POSTGRESQL.ORG/DOCS/CURRENT/... ) est généralement plus rapide qu'un cas code> à l'intérieur d'un compte.
Une optimisation serait de ne pas exécuter la sous-requête une fois et d'utiliser une agrégation conditionnelle pour compter les sièges:
SELECT * FROM trips JOIN dates on dates.id = trips.trip_date WHERE places_number_on_flag > 0 AND places_number > 0 AND ( places_number - ( (SELECT Count(id) + count(id) filter (where extra_seat = 1) FROM resrv_customers WHERE trip = trips.id AND ow > 0)) < 20 ) AND dates.from_date > 2458553;
J'ajouterais: Utilisez des noms de variables au lieu de "*". Et rappelez-vous, Expliquez Analyser vous aidera à connaître le coût de chaque étape.
Essayez ceci:
with rc_count as ( select trip, count(*) as ow_count, sum( (extra_seat = 1)::int ) as ow_count_with_extra_seat from resrv_customers where ow > 0 group by trip ) SELECT * FROM trips join dates on dates.id = trips.trip_date join rc_count rc on trips.id = trip WHERE places_number_on_flag > 0 AND places_number > 0 AND dates.from_date > 2458553 and places_number - (ow_count + ow_count_with_extra_seat) < 20
Remarque: cette réponse est presque identique à ce que j'ai posté plus tôt.
@TimbieGeleisen n'a pas remarqué cela. Je me suis concentré sur la rédaction de ma propre réponse et j'ai également déplacé la condition partagée ow> 0 code> à l'endroit où la clause
Avez-vous consulté le plan d'exécution?
Veuillez afficher le tableau
Créer le tableau code> et
Créer une index code> Index plus le plan. Vous devez également retravailler la requête en utilisant une syntaxe de jointure explicite pour une meilleure lisibilité.
@dodekja. . . Vous devez expliquer quelle logique la requête met en œuvre.
Mauvaises habitudes de frappe: Utiliser des jointures de style anciennes - que la liste des tables Séparation des virgules i> a été remplacée par le approprié i> ansi
rejoindre code> Syntaxe dans l'ANSI- 92 B> SQL Standard ( 25 ans B> Il y a) et son utilisation est découragée