PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 14/01/2016 15:57:39

thomasp
Membre

Row_number() très long en vue, très rapide en requête direct

Bonjour à tous,
J'ai une vue qui est très longue à interroger (environ 30 secondes) alors qu'en utilisant directement la requête de construction de la vue, la réponse est instantanée.

C'est un row_number() over(...) qui rend la lecture de la vue très longue (quand j'a fait une 2ème vue avec le row_number en moins, sa lecture est très rapide), alors qu'en requête direct c'est très rapide.

Savez-vous d'où peut venir ce problème ?

Merci

Dernière modification par thomasp (14/01/2016 16:53:34)

Hors ligne

#2 14/01/2016 16:08:57

ruizsebastien
Membre

Re : Row_number() très long en vue, très rapide en requête direct

Bonjour,

C'est une vue matérialisée ou une vue simple ?


Cordialement.

Dernière modification par ruizsebastien (14/01/2016 16:10:23)


Cordialement,

Sébastien.

Hors ligne

#3 14/01/2016 16:20:28

thomasp
Membre

Re : Row_number() très long en vue, très rapide en requête direct

Non ce n'est pas une vue matérialisée.

Voici grosso modo ce qui est fait :

-- création de la vue :
create view mavue as
  select user,
     row_number() over(partition by iduser order by importance)
  from (
    select user,
       case when year > 2010 then 1
               when year between 2005 and 2010 then 2
               when year < 2005 then 3 
               end as importance
    from ma table) as t;

-- interrogation de la vue, TRES LONG :
select * from mavue where user = '123456';

-- interrogation via la requête de la vue, TRES RAPIDE :
select user,
   row_number() over(parittion by iduser order by importance)
from (
  select user,
    case when year > 2010 then 1
             when year between 2005 and 2010 then 2
             when year < 2005 then 3 else 4 end as importance
  from ma table) as t
where user = '123456';

Dernière modification par thomasp (15/01/2016 17:16:01)

Hors ligne

#4 14/01/2016 16:56:35

rjuju
Administrateur

Re : Row_number() très long en vue, très rapide en requête direct

Pouvez-vous montrer la définition de la vue, un EXPLAIN (ANALYZE, BUFFERS) de la vue ainsi que de la requête en direct ?

Hors ligne

#5 14/01/2016 16:58:09

ruizsebastien
Membre

Re : Row_number() très long en vue, très rapide en requête direct

@ThomasP : Vous dites que les 2 requêtes ne sont pas identiques ?

Dernière modification par ruizsebastien (14/01/2016 17:00:10)


Cordialement,

Sébastien.

Hors ligne

#6 15/01/2016 11:27:18

thomasp
Membre

Re : Row_number() très long en vue, très rapide en requête direct

@ruizsebastien : Les résultats sont indentiques, c'est le temps d'interrogation de la vue qui est à 30s contre résultat instantané via la requête.
J'ai l'impression que pour pouvoir effectuer la window function row_number(), la vue a besoin d'effectuer l'intégralité des résultats et ne filtre qu'ensuite sur le user contrairement à la requête qui filtre tout de suite.

Voici l'explain via la vue :

-- requête :
select * from v_test where iduser = '123456';

-- explain:

QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------
 Subquery Scan on v_test  (cost=11676104.30..13758879.44 rows=122516 width=88) (actual time=121199.140..121199.140 rows=0 loops=1)
   Filter: (v_test.iduser = '123456'::uuid)
   Rows Removed by Filter: 934344
   Buffers: shared hit=124590, temp read=524249 written=524249
   ->  WindowAgg  (cost=11676104.30..13452588.98 rows=24503237 width=48) (actual time=120453.051..121084.875 rows=934344 loops=1)
         Buffers: shared hit=124590, temp read=524249 written=524249
         ->  Sort  (cost=11676104.30..11737362.39 rows=24503237 width=48) (actual time=120453.043..120628.260 rows=934344 loops=1)
               Sort Key: k.iduser, (CASE WHEN ((0::double precision <= k.similarity) AND (k.similarity < 0.1::double precision) AND (k.nb_link >= 4)) THEN 0.90 WHEN ((0.1::double precision <= k.similarity) AND (k.similarity < 0.5::double
precision) AND (k.nb_link >= 4)) THEN 0.80 WHEN ((0.5::double precision <= k.similarity) AND (k.similarity < 1::double precision) AND (k.nb_link >= 4)) THEN 0.70 WHEN ((0::double precision <= k.similarity) AND (k.similarity < 0.1::double prec
ision) AND (k.nb_link = 3)) THEN 0.60 WHEN ((0.1::double precision <= k.similarity) AND (k.similarity < 0.5::double precision) AND (k.nb_link = 3)) THEN 0.55 WHEN ((0.5::double precision <= k.similarity) AND (k.similarity < 1::double precisio
n) AND (k.nb_link = 3)) THEN 0.50 WHEN ((0::double precision <= k.similarity) AND (k.similarity <= 1::double precision) AND (k.nb_link = 1)) THEN 0.50 ELSE 0.0 END)
               Sort Method: external sort  Disk: 60288kB
               Buffers: shared hit=124590, temp read=524249 written=524249
               ->  Subquery Scan on k  (cost=5243570.30..6407474.06 rows=24503237 width=48) (actual time=85447.404..118161.244 rows=934344 loops=1)
                     Buffers: shared hit=124590, temp read=516713 written=516713
                     ->  GroupAggregate  (cost=5243570.30..6162441.69 rows=24503237 width=36) (actual time=85447.390..117024.041 rows=934344 loops=1)
                           Group Key: p1.iduser, p2.iduser
                           Filter: (count(p1.iduser) >= 3)
                           Rows Removed by Filter: 20710574
                           Buffers: shared hit=124590, temp read=516713 written=516713
                           ->  Sort  (cost=5243570.30..5304828.40 rows=24503237 width=36) (actual time=85447.331..99172.607 rows=26463224 loops=1)
                                 Sort Key: p1.iduser, p2.iduser
                                 Sort Method: external merge  Disk: 1189976kB
                                 Buffers: shared hit=124590, temp read=516713 written=516713
                                 ->  Merge Join  (cost=458597.79..896206.56 rows=24503237 width=36) (actual time=4440.491..17662.837 rows=26463224 loops=1)
                                       Merge Cond: (p1.idplace = p2.idplace)
                                       Join Filter: (p2.iduser <> p1.iduser)
                                       Rows Removed by Join Filter: 1165656
                                       Buffers: shared hit=124590, temp read=15494 written=15494
                                       ->  Sort  (cost=229298.90..232223.81 rows=1169965 width=34) (actual time=2224.805..3029.659 rows=1165656 loops=1)
                                             Sort Key: p1.idplace
                                             Sort Method: external merge  Disk: 50064kB
                                             Buffers: shared hit=62295, temp read=7747 written=7747
                                             ->  Seq Scan on MaTable p1  (cost=0.00..79384.43 rows=1169965 width=34) (actual time=0.116..533.186 rows=1165656 loops=1)
                                                   Filter: (note <> 0)
                                                   Rows Removed by Filter: 195531
                                                   Buffers: shared hit=62295
                                       ->  Materialize  (cost=229298.90..235148.72 rows=1169965 width=34) (actual time=2215.665..5624.362 rows=27628880 loops=1)
                                             Buffers: shared hit=62295, temp read=7747 written=7747
                                             ->  Sort  (cost=229298.90..232223.81 rows=1169965 width=34) (actual time=2215.659..2972.700 rows=1165656 loops=1)
                                                   Sort Key: p2.idplace
                                                   Sort Method: external merge  Disk: 50064kB
                                                   Buffers: shared hit=62295, temp read=7747 written=7747
                                                   ->  Seq Scan on MaTable p2  (cost=0.00..79384.43 rows=1169965 width=34) (actual time=0.081..526.648 rows=1165656 loops=1)
                                                         Filter: (note <> 0)
                                                         Rows Removed by Filter: 195531
                                                         Buffers: shared hit=62295
 Planning time: 1.199 ms
 Execution time: 121506.464 ms

et voici l'explain de la requête directe :

-- requête :
select *, row_number() over(parition by iduser order by trust desc)
from (
	SELECT 
		iduser, iduser_same, similarity, nb_link,
		CASE 
			WHEN 0.0 <= k.similarity AND k.similarity < 0.1 AND k.nb_link >= 4 THEN 0.90
			WHEN 0.1 <= k.similarity AND k.similarity < 0.5 AND k.nb_link >= 4 THEN 0.80
			WHEN 0.5 <= k.similarity AND k.similarity < 1.0 AND k.nb_link >= 4 then 0.70
			WHEN 0.0 <= k.similarity AND k.similarity < 0.1 AND k.nb_link = 3 THEN 0.60
			WHEN 0.1 <= k.similarity AND k.similarity < 0.5 AND k.nb_link = 3 THEN 0.55
			WHEN 0.5 <= k.similarity AND k.similarity < 1.0 AND k.nb_link = 3 THEN 0.50
			WHEN 0.0 <= k.similarity AND k.similarity <= 1.0 AND k.nb_link = 1 THEN 0.50
			ELSE 0.0 END AS trust
	FROM (
		SELECT 
			p1.iduser AS iduser, p2.iduser AS iduser_same, 
			AVG(ABS(p1.note - p2.note)::float) AS similarity, 
			COUNT(p1.iduser) AS nb_link
		FROM MaTable as p1
			INNER JOIN MaTable as p2 ON p1.idplace = p2.idplace
		WHERE p1.note != 0
		AND p2.note != 0
		AND p2.iduser != p1.iduser
		GROUP BY p1.iduser, p2.iduser
		HAVING COUNT(p1.iduser) >= 3) k) as t
where iduser = '123456';

-- explain :

QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
 WindowAgg  (cost=1812.92..1852.47 rows=565 width=48) (actual time=0.050..0.050 rows=0 loops=1)
   Buffers: shared hit=3
   ->  Sort  (cost=1812.92..1814.33 rows=565 width=48) (actual time=0.048..0.048 rows=0 loops=1)
         Sort Key: (CASE WHEN ((0::double precision <= k.similarity) AND (k.similarity < 0.1::double precision) AND (k.nb_links >= 4)) THEN 0.90 WHEN ((0.1::double precision <= k.similarity) AND (k.similarity < 0.5::double precision) AND (k.
nb_links >= 4)) THEN 0.80 WHEN ((0.5::double precision <= k.similarity) AND (k.similarity < 1::double precision) AND (k.nb_links >= 4)) THEN 0.70 WHEN ((0::double precision <= k.similarity) AND (k.similarity < 0.1::double precision) AND (k.nb_link
s = 3)) THEN 0.60 WHEN ((0.1::double precision <= k.similarity) AND (k.similarity < 0.5::double precision) AND (k.nb_links = 3)) THEN 0.55 WHEN ((0.5::double precision <= k.similarity) AND (k.similarity < 1::double precision) AND (k.nb_links =
3)) THEN 0.50 WHEN ((0::double precision <= k.similarity) AND (k.similarity <= 1::double precision) AND (k.nb_links = 1)) THEN 0.50 ELSE 0.0 END)
         Sort Method: quicksort  Memory: 25kB
         Buffers: shared hit=3
         ->  Subquery Scan on k  (cost=1772.97..1787.09 rows=565 width=48) (actual time=0.032..0.032 rows=0 loops=1)
               Buffers: shared hit=3
               ->  HashAggregate  (cost=1772.97..1781.44 rows=565 width=36) (actual time=0.031..0.031 rows=0 loops=1)
                     Group Key: p1.iduser, p2.iduser
                     Filter: (count(p1.iduser) >= 3)
                     Buffers: shared hit=3
                     ->  Nested Loop  (cost=9.33..1761.67 rows=565 width=36) (actual time=0.027..0.027 rows=0 loops=1)
                           Buffers: shared hit=3
                           ->  Bitmap Heap Scan on MaTable p1  (cost=4.67..130.98 rows=27 width=34) (actual time=0.026..0.026 rows=0 loops=1)
                                 Recheck Cond: (iduser = '123456'::uuid)
                                 Filter: (note <> 0)
                                 Buffers: shared hit=3
                                 ->  Bitmap Index Scan on ix_poi_note_engine_iduser  (cost=0.00..4.67 rows=32 width=0) (actual time=0.019..0.019 rows=0 loops=1)
                                       Index Cond: (iduser = '123456'::uuid)
                                       Buffers: shared hit=3
                           ->  Bitmap Heap Scan on MaTable p2  (cost=4.66..60.28 rows=12 width=34) (never executed)
                                 Recheck Cond: (idplace = p1.idplace)
                                 Filter: ((note <> 0) AND (iduser <> p1.iduser))
                                 ->  Bitmap Index Scan on pk_MaTable  (cost=0.00..4.66 rows=14 width=0) (never executed)
                                       Index Cond: (idplace = p1.idplace)
 Planning time: 1.139 ms
 Execution time: 0.285 ms

Dernière modification par thomasp (15/01/2016 17:05:02)

Hors ligne

#7 15/01/2016 13:49:50

rjuju
Administrateur

Re : Row_number() très long en vue, très rapide en requête direct

Pouvez-vous fournir la définition de la vue ? À priori quand vous utilisez la vue le WHERE iduser = '123456' n'est pas poussé dans la requête.

Hors ligne

#8 15/01/2016 15:26:44

thomasp
Membre

Re : Row_number() très long en vue, très rapide en requête direct

La définition de la vue est exactement comme la requête (sans bien sûr la clause sur le user) :

create view v_test as
select *, row_number() over(parition by iduser order by trust desc)
from (
	SELECT 
		iduser, iduser_same, similarity, nb_link,
		CASE 
			WHEN 0.0 <= k.similarity AND k.similarity < 0.1 AND k.nb_link >= 4 THEN 0.90
			WHEN 0.1 <= k.similarity AND k.similarity < 0.5 AND k.nb_link >= 4 THEN 0.80
			WHEN 0.5 <= k.similarity AND k.similarity < 1.0 AND k.nb_link >= 4 then 0.70
			WHEN 0.0 <= k.similarity AND k.similarity < 0.1 AND k.nb_link = 3 THEN 0.60
			WHEN 0.1 <= k.similarity AND k.similarity < 0.5 AND k.nb_link = 3 THEN 0.55
			WHEN 0.5 <= k.similarity AND k.similarity < 1.0 AND k.nb_link = 3 THEN 0.50
			WHEN 0.0 <= k.similarity AND k.similarity <= 1.0 AND k.nb_link = 1 THEN 0.50
			ELSE 0.0 END AS trust
	FROM (
		SELECT 
			p1.iduser AS iduser, p2.iduser AS iduser_same, 
			AVG(ABS(p1.note - p2.note)::float) AS similarity, 
			COUNT(p1.iduser) AS nb_link
		FROM MaTable as p1
			INNER JOIN MaTable as p2 ON p1.idplace = p2.idplace
		WHERE p1.note != 0
		AND p2.note != 0
		AND p2.iduser != p1.iduser
		GROUP BY p1.iduser, p2.iduser
		HAVING COUNT(p1.iduser) >= 3) k) as t);

Dernière modification par thomasp (15/01/2016 17:04:19)

Hors ligne

#9 15/01/2016 15:57:55

rjuju
Administrateur

Re : Row_number() très long en vue, très rapide en requête direct

Je suis sceptique sur le "row_number" sans parenthèse et le "parition by", de même que vous sélectionnez des colonnes qui n'existent pas (iduser_same n'est pas présent dans le sous select). Étant donné que les requêtes que vous fournissez depuis le début ne sont pas syntaxiquement correctes, je vois mal comment vous pouvez donner vos chiffres.

Hors ligne

#10 15/01/2016 17:15:14

thomasp
Membre

Re : Row_number() très long en vue, très rapide en requête direct

oui vous avez raison, c'est parce que j'ai changé (un peu trop vite) les noms pour que ce soit plus lisible. J'ai édité le code précédent pour avoir les noms qui collent bien. Merci

Hors ligne

#11 15/01/2016 17:25:16

rjuju
Administrateur

Re : Row_number() très long en vue, très rapide en requête direct

Et votre requête n'est toujours pas correcte.

Hors ligne

Pied de page des forums