Nous avons une requête complexe qui a été très lente. J'ai réussi à réduire la requête à une simple reproduction. Il semble que la combinaison de greatest
et log
en soit la cause, mais je ne comprends pas pourquoi.
Voici un exemple sql-fiddle complet pour exécuter les requêtes - et vous pouvez également View the execution Plans
Des requêtes (appuyez sur le lien en bas du résultat de la requête sur le sql- page violon)
Voici donc la requête lente :
select count(value)
from (
SELECT log(greatest(1e-9, x)) as value
from (select generate_series(1, 20000, 1) as x) as d
) t;
Nous générons simplement une série de nombres de 20k et utilisons log(greatest())
. Cette requête prend environ 1,5 secondes.
Je pensais que le calcul du journal peut prendre du temps, mais la requête suivante est également rapide ( ~ 5ms ):
select count(value)
from (
SELECT log(x) as value
from (select generate_series(1, 20000, 1) as x) as d
) t;
Tout comme un test, j'ai échangé greatest
et log
- c'est aussi rapide ( ~ 5ms ):
select count(value)
from (
SELECT greatest(1e-9, log(x)) as value
from (select generate_series(1, 20000, 1) as x) as d
) t;
Les QUERY PLANS
Pour les 3 requêtes sont les mêmes:
Aggregate (cost=22.51..22.52 rows=1 width=8)
-> Result (cost=0.00..5.01 rows=1000 width=4)
Quelqu'un peut-il expliquer pourquoi la première requête est si lente - et peut-être que quelqu'un connaît une solution?
J'obtiens des résultats similaires sur tous ces éléments (la première requête est d'une amplitude plus lente):
Lorsque je change count(value)
en count(*)
ou count(1)
(numéro un) la requête est rapide
Vous invoquez deux fonctions de journal différentes ici: log(numeric,numeric)
et log(double precision)
, et la première est beaucoup plus lente que la seconde.
Remarquez comment les fonctions d'appel diffèrent dans EXPLAIN (ANALYZE, VERBOSE) ci-dessous, exécuté avec PostgreSQL 11.5 (Linux Ubuntu):
Version lente:
explain (analyze, verbose) select count(value)
from (
SELECT log(greatest(1e-9, x)) as value
from (select generate_series(1, 20000, 1) as x) as d
) t;
QUERY PLAN
-------------------------------------------------------------------------------------------------------
Aggregate (cost=25.02..25.03 rows=1 width=8) (actual time=1174.349..1174.349 rows=1 loops=1)
Output: count(log('10'::numeric, GREATEST(0.000000001, ((generate_series(1, 20000, 1)))::numeric)))
-> ProjectSet (cost=0.00..5.02 rows=1000 width=4) (actual time=0.004..1.310 rows=20000 loops=1)
Output: generate_series(1, 20000, 1)
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=1)
Planning Time: 0.123 ms
Execution Time: 1174.385 ms
Version rapide:
explain (analyze, verbose) select count(value)
from (
SELECT log(greatest(1e-9::float, x)) as value
from (select generate_series(1, 20000, 1) as x) as d
) t;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
Aggregate (cost=25.02..25.03 rows=1 width=8) (actual time=6.693..6.693 rows=1 loops=1)
Output: count(log(GREATEST('1e-09'::double precision, ((generate_series(1, 20000, 1)))::double precision)))
-> ProjectSet (cost=0.00..5.02 rows=1000 width=4) (actual time=0.004..2.561 rows=20000 loops=1)
Output: generate_series(1, 20000, 1)
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=1)
Planning Time: 0.096 ms
Execution Time: 6.731 ms
greatest()
n'est pas responsable: si l'on considère la requête avec juste log(x)
, si vous transtypez x
en numeric
ce sera aussi lent avec ou sans greatest()
.