Domanda

Ho la seguente tabella:

id message_read notification_sent send_date           text                                                version recipient sender 
-- ------------ ----------------- ------------------- --------------------------------------------------- ------- --------- ------ 
1  true         false             2015-02-27 00:00:00 Bonjour. Je suis disponible pour la garde partagée. 0       2         3      
3  false        false             2015-03-01 00:00:00 Je suis disponible pour vous rencontrer dès demain. 0       2         3      
12 false        false             2015-02-27 00:00:00 Hello dude                                          0       2         1      
.

La query qui sotto è il tipo di query che in genere vengono eseguite su questa tabella:

select * from public.message
where (recipient = 2 and sender = 3) or (sender = 2 and recipient = 3);
.

Sto cercando di creare indici efficienti su questa tabella e tenendo presente che il tipo di query funziona su di esso.

Ecco i miei indici:

CREATE INDEX recipient_idx ON message(recipient);
CREATE INDEX sender_idx ON message(sender);
.

Ed ecco l'output di un explain analyze sulla query sopra:

QUERY PLAN                                                                                                                  
--------------------------------------------------------------------------------------------------------------------------  
Bitmap Heap Scan on message  (cost=8.57..13.40 rows=1 width=49) (actual time=0.072..0.075 rows=3 loops=1)                   
  Recheck Cond: ((sender = 3) OR (recipient = 3))                                                                           
  Filter: (((recipient = 2) AND (sender = 3)) OR ((sender = 2) AND (recipient = 3)))                                        
  Heap Blocks: exact=1                                                                                                      
  ->  BitmapOr  (cost=8.57..8.57 rows=2 width=0) (actual time=0.050..0.050 rows=0 loops=1)                                  
        ->  Bitmap Index Scan on sender_idx  (cost=0.00..4.28 rows=1 width=0) (actual time=0.037..0.037 rows=2 loops=1)     
              Index Cond: (sender = 3)                                                                                      
        ->  Bitmap Index Scan on recipient_idx  (cost=0.00..4.28 rows=1 width=0) (actual time=0.009..0.009 rows=1 loops=1)  
              Index Cond: (recipient = 3)                                                                                   
Planning time: 0.468 ms                                                                                                     
Execution time: 0.188 ms    
.

Qualcuno può dirmi cosa sto sbagliando?Perché la mia query non è usando un indice btree e un bitmap invece?Come posso migliorare i miei indici?

Modifica :

Ecco cosa ho provato:

CREATE INDEX recipient_sender_idx ON message(recipient, sender);
.

Esecuzione dell'analisi dello spiegamento Ora rendono:

QUERY PLAN                                                                                                                  
--------------------------------------------------------------------------------------------------------------------------  
Bitmap Heap Scan on message  (cost=8.57..13.40 rows=1 width=49) (actual time=0.035..0.038 rows=3 loops=1)                   
  Recheck Cond: ((sender = 3) OR (recipient = 3))                                                                           
  Filter: (((recipient = 2) AND (sender = 3)) OR ((sender = 2) AND (recipient = 3)))                                        
  Heap Blocks: exact=1                                                                                                      
  ->  BitmapOr  (cost=8.57..8.57 rows=2 width=0) (actual time=0.023..0.023 rows=0 loops=1)                                  
        ->  Bitmap Index Scan on sender_idx  (cost=0.00..4.28 rows=1 width=0) (actual time=0.015..0.015 rows=2 loops=1)     
              Index Cond: (sender = 3)                                                                                      
        ->  Bitmap Index Scan on recipient_idx  (cost=0.00..4.28 rows=1 width=0) (actual time=0.007..0.007 rows=1 loops=1)  
              Index Cond: (recipient = 3)                                                                                   
Planning time: 0.183 ms                                                                                                     
Execution time: 0.070 ms   
.

Modifica 2 :

explain analyze
select * from public.message
where recipient = 2 and sender = 3 
UNION ALL
select * from public.message
where sender = 2 and recipient = 3
.

rendimenti:

QUERY PLAN                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------  
Append  (cost=0.29..16.63 rows=2 width=49) (actual time=0.031..0.043 rows=3 loops=1)                                                           
  ->  Index Scan using recipient_sender_idx on message  (cost=0.29..8.31 rows=1 width=49) (actual time=0.030..0.031 rows=2 loops=1)            
        Index Cond: ((recipient = 2) AND (sender = 3))                                                                                         
  ->  Index Scan using recipient_sender_idx on message message_1  (cost=0.29..8.31 rows=1 width=49) (actual time=0.009..0.010 rows=1 loops=1)  
        Index Cond: ((recipient = 3) AND (sender = 2))                                                                                         
Planning time: 0.389 ms                                                                                                                        
Execution time: 0.075 ms                                                                                                  
.

Ma non è fattibile modificare la mia query SQL.

È stato utile?

Soluzione

Penso che la ragione per cui seleziona i singoli indici e oring li sia che i tuoi dati siano di dimensioni del giocattolo; Testimone:

  ->  BitmapOr  (rows=0 loops=1)                                  
        ->  Bitmap Index Scan on sender_idx  (rows=2 loops=1)     
              Index Cond: (sender = 3)                                                                                      
        ->  Bitmap Index Scan on recipient_idx  (rows=1 loops=1)  
              Index Cond: (recipient = 3)    
.

e

    scanned 101 of 101 pages, containing 9642 live rows
.

La tabella è piuttosto piccola e gli indici sono altamente selettivi, quindi probabilmente è più veloce di scansionare gli indici più piccoli, quindi filtrare i risultati. Non c'è punto di utilizzare un indice composito quando gli indici singolari trovano comunque un paio di righe.


.

Se i dati sono stati più grandi e / o c'erano più righe per un determinato mittente / destinatario, dovrebbe idealmente utilizzare due scansioni indice indipendenti su un indice composito, quindi fondersi. Non penso che il pianificatore sia abbastanza intelligente da capire che questo può essere eseguito come due domande e UNIONed, però, quindi il meglio che otterrai è probabilmente due scansioni indice bitmap sull'indice composita, quindi un bitmapor. < / P >.

Prova:

select * from public.message
where recipient = 2 and sender = 3 
UNION ALL
select * from public.message
sender = 2 and recipient = 3;
.

Per vedere se il piano scelto è più vicino a quello che vuoi. Anche se produce il piano desiderato, con due nodi Indexcan sull'indice compositario, quindi un nodo APPEND per l'Unione, potrebbe effettivamente essere più lento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a dba.stackexchange
scroll top