2015-05-20 19 views
5

su postgresl 9.0 abbiamo una query SQL:Una query PostgreSQL non finirà

SELECT count(*) FROM lane 
WHERE not exists 
    (SELECT 1 FROM id_map 
    WHERE id_map.new_id=lane.lane_id 
    and id_map.column_name='lane_id' 
    and id_map.table_name='lane') 
and lane.lane_id is not null; 

che prende di solito un po 'di circa 1,5 secondi per terminare. Ecco il piano di spiegazioni: http://explain.depesz.com/s/axNN

A volte però questa query si blocca e non si concluderà. Può funzionare anche per 11 ore senza successo. Quindi occupa il 100% della CPU.

Gli unici blocchi utilizzati da questa query sono "AccessShareLock" e sono tutti concessi.

SELECT a.datname, 
     c.relname, 
     l.transactionid, 
     l.mode, 
     l.granted, 
     a.usename, 
     a.current_query, 
     a.query_start, 
     age(now(), a.query_start) AS "age", 
     a.procpid 
    FROM pg_stat_activity a 
    JOIN pg_locks   l ON l.pid = a.procpid 
    JOIN pg_class   c ON c.oid = l.relation 
    ORDER BY a.query_start; 

La query viene eseguita come parte di un processo di Java che si connette a un database utilizzando un pool di connessioni ed esegue query di selezione sequenziale simili di questo formato:

SELECT count(*) FROM {} WHERE not exists (SELECT 1 FROM id_map WHERE id_map.new_id={}.{} and id_map.column_name='{}' and id_map.table_name='{}') and {}.{} is not null 

aggiornamenti o cancellare stanno accadendo parallelamente a questo processo, quindi non penso che l'aspirazione sia il problema qui. Prima di eseguire l'intero processo (quindi prima dell'esecuzione di 6 query di questo tipo) è stata eseguita un'analisi su tutte le tabelle.

I registri postgres non mostrano alcuna voce per le query di lunga durata perché non terminano mai e quindi non vengono mai registrati.

Qualche idea su cosa potrebbe causare questo tipo di comportamento e su come impedire che ciò accada?

il piano di spiegare, senza analizzare:

Aggregate (cost=874337.91..874337.92 rows=1 width=0) 
    -> Nested Loop Anti Join (cost=0.00..870424.70 rows=1565283 width=0) 
     Join Filter: (id_map.new_id = lane.lane_id) 
     -> Seq Scan on lane (cost=0.00..30281.84 rows=1565284 width=8) 
       Filter: (lane_id IS NOT NULL) 
     -> Materialize (cost=0.00..816663.60 rows=1 width=8) 
       -> Seq Scan on id_map (cost=0.00..816663.60 rows=1 width=8) 
        Filter: (((column_name)::text = 'lane_id'::text) AND ((table_name)::text = 'lane'::text)) 
+0

ho avuto lo stesso problema con Java . Non era la versione postgres - era java non terminando la connessione ... 100% CPU di postgres o java? .. cosa c'è in pg_stat_activity? .. –

+0

100% di postgres. pg_stat_activity mostra una query sql infinita – norbitheeviljester

+0

quando va al 100% della CPU, puoi controllare il piano? .. Potrebbe essere cicli annidati invece di join hash - il che significherebbe dare troppo poca RAM per il caching ... Un altro approccio è " come sono fresche le statistiche "Ma entrambe valgono la pena di studiare se il piano di esecuzione differisce quando colpisce il 100% CPU –

risposta

5
VACUUM ANALYZE VERBOSE; 

statistiche refrigerio aiutare db di scegliere piano ottimale - loop non nidificati, che credo prendere il 100% della CPU

+0

Sono riuscito a verificare che questa fosse effettivamente la causa principale del problema. Il ciclo annidato crea 1,5 milioni di scansioni di sequenza della tabella id_map che impiega giorni per terminare. Quando si esegue un'analisi del vuoto su entrambe le tabelle prima dell'esecuzione della query, la query termina in meno di 2 secondi. – norbitheeviljester

Problemi correlati