Domanda

Ho eseguito un AGGIORNAMENTO su una tabella contenente 250 milioni di righe con 3 indici '; questo AGGIORNAMENTO utilizza un'altra tabella contenente 30 milioni di righe. Funziona da circa 36 ore. Mi chiedo se il loro è un modo per scoprire quanto è vicino se si prevede di impiegare un milione di giorni per fare la sua cosa, la ucciderò; ma se ha bisogno solo di un altro giorno o due, lo lascerò correre. Ecco la query di comando:

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0
;

EXPLAIN non è il problema qui e cito solo che il tavolo grande ha più indici al fine di giustificare in qualche modo il tempo necessario per aggiornarlo. Ma ecco comunque EXPLAIN:

Merge Join  (cost=127710692.21..135714045.43 rows=452882848 width=57)
  Merge Cond: (("outer".page_namespace = "inner".pl_namespace) AND ("outer"."?column4?" = "inner"."?column5?"))
  ->  Sort  (cost=3193335.39..3219544.38 rows=10483593 width=41)
        Sort Key: page.page_namespace, (page.page_title)::text
        ->  Seq Scan on page  (cost=0.00..439678.01 rows=10483593 width=41)
              Filter: (page_is_redirect = 0::numeric)
  ->  Sort  (cost=124517356.82..125285665.74 rows=307323566 width=46)
        Sort Key: pagelinks.pl_namespace, (pagelinks.pl_title)::text"
        ->  Seq Scan on pagelinks  (cost=0.00..6169460.66 rows=307323566 width=46)

Ora ho anche inviato un comando query parallelo per DROP uno degli indici pagelink '; ovviamente sta aspettando che finisca l'AGGIORNAMENTO (ma mi andava di provarlo comunque!). Quindi, non posso SELEZIONARE nulla da pagelink per paura di corrompere i dati (a meno che non pensi che sarebbe sicuro uccidere il processo postmaster DROP INDEX?).

Quindi mi chiedo se il loro è un tavolo che tenga traccia della quantità di tuple morte o qualcosa del genere Sarebbe bello sapere quanto velocemente o quanto è lontano l'AGGIORNAMENTO nel completamento del suo compito.

Thx (PostgreSQL non è intelligente come pensavo; ha bisogno di euristica)

È stato utile?

Soluzione

Hai letto la documentazione di PostgreSQL per " Uso di EXPLAIN " ;, per interpretare l'output che stai mostrando?

Non sono un normale utente PostgreSQL, ma ho appena letto quel documento e poi confrontato con l'output EXPLAIN che stai mostrando. La tua query UPDATE sembra non utilizzare alcun indice ed è costretta a eseguire scansioni di tabelle per ordinare sia page che pagelink . L'ordinamento è senza dubbio abbastanza grande da richiedere file temporanei su disco, che credo siano creati sotto il tuo temp_tablespace .

Quindi vedo leggere le pagine del database stimate. Il livello superiore di tale output EXPLAIN indica (costo = 127710692.21..135714045.43) . Le unità qui sono in accessi I / O su disco. Quindi accederà al disco oltre 135 milioni di volte per eseguire questo UPDATE .

Si noti che anche i dischi a 10.000 rpm con tempo di ricerca di 5 ms possono ottenere al massimo 200 operazioni di I / O al secondo in condizioni ottimali. Ciò significherebbe che il tuo AGGIORNAMENTO richiederebbe 188 ore (7,8 giorni) di I / O su disco, anche se potresti sostenere I / O su disco saturo per quel periodo (ovvero letture / scritture continue senza interruzioni) . Questo è impossibile, e mi aspetto che il throughput effettivo sia disattivato di almeno un ordine di grandezza, soprattutto perché nel frattempo non hai sicuramente usato questo server per qualsiasi altro lavoro. Quindi immagino che tu sia solo una frazione del tuo AGGIORNAMENTO .

Se fossi stato io, avrei ucciso questa query il primo giorno e avrei trovato un altro modo di eseguire il UPDATE che faceva un uso migliore degli indici e non richiedeva l'ordinamento su disco. Probabilmente non puoi farlo in una singola istruzione SQL.

Per quanto riguarda il tuo DROP INDEX , immagino che stia semplicemente bloccando, aspettando l'accesso esclusivo al tavolo e mentre è in questo stato penso che probabilmente potresti ucciderlo.

Altri suggerimenti

Questo è molto vecchio, ma se vuoi un modo per monitorare il tuo aggiornamento ... Ricorda che le sequenze sono influenzate a livello globale, quindi puoi semplicemente crearne uno per monitore questo aggiornamento in un'altra sessione facendo questo:

create sequence yourprogress; 

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0 AND NEXTVAL('yourprogress')!=0;

Quindi in un'altra sessione fai questo (non preoccuparti delle transazioni, poiché le sequenze sono influenzate a livello globale):

select last_value from yourprogress;

Questo mostrerà quante linee sono interessate, quindi puoi stimare quanto tempo impiegherai.

Alla fine riavvia la sequenza per riprovare:

alter sequence yourprogress restart with 1;

O semplicemente rilasciarlo:

drop sequence yourprogress;

Hai bisogno di indici o, come ha sottolineato Bill, dovrà fare scansioni sequenziali su tutte le tabelle.

CREATE INDEX page_ns_title_idx on page(page_namespace, page_title);
CREATE INDEX pl_ns_title_idx on pagelink(pl_namespace, pl_title);
CREATE INDEX page_redir_idx on page(page_is_redirect);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top