REINDEX è pericoloso?


17

Ho provato a COUNT(*)una tabella con 150.000 righe con una chiave primaria. Strumento di circa 5 minuti, quindi ho capito che questo è un problema di indicizzazione.

Citando il manuale PostgreSQL :

REINDEX è simile a una goccia e ricrea l'indice in quanto i contenuti dell'indice vengono ricostruiti da zero. Tuttavia, le considerazioni sul blocco sono piuttosto diverse. REINDEX blocca le scritture ma non le letture della tabella padre dell'indice. Richiede anche un blocco esclusivo sull'indice specifico in fase di elaborazione, che bloccherà le letture che tentano di utilizzare quell'indice (...) Il successivo CREATE INDEX blocca le scritture ma non le letture; poiché l'indice non è presente, nessuna lettura tenterà di utilizzarlo, il che significa che non ci saranno blocchi ma le letture potrebbero essere forzate in costose scansioni sequenziali.

Dalla tua esperienza, puoi dire:

  • è REINDEXINGpericoloso? Può danneggiare la coerenza dei dati?
  • Può volerci molto tempo?
  • È una soluzione probabile al mio scenario?

Aggiornare:

La soluzione che ha funzionato per noi è stata ricreare lo stesso indice con un nome diverso, quindi eliminare il vecchio indice.

La creazione dell'indice è molto rapida e abbiamo ridotto le dimensioni dell'indice da 650 MB a 8 MB. L'uso di COUNT(*)a betweenrichiede solo 3 secondi.

Risposte:


15

La reindicizzazione non è pericolosa e non può danneggiare la coerenza dei dati. Tuttavia, se si dispone di scritture temporali, è possibile perdere dati se la tabella è bloccata e il DML viene interrotto.

La reindicizzazione non dovrebbe richiedere molto tempo, ma di solito implica la lettura dell'intera tabella, l'ordinamento dei campi dell'indice e la scrittura di un nuovo indice. Dato il tempo COUNT(*), probabilmente impiegherà almeno cinque minuti.

È improbabile che si tratti di un problema di indicizzazione. COUNT(*)dovrebbe utilizzare una scansione della tabella, nel qual caso non viene letto alcun indice. Mi aspetto che tu abbia un problema IO di qualche tipo.

Prova a utilizzare COUNT(1)o COUNT(pk_field)che potrebbe utilizzare l'indice.

Se stai utilizzando una piattaforma Unix o Linux, potresti voler monitorare l'attività del disco con sar. Potresti anche avere un disco guasto che può ridurre drasticamente i tassi di IO.

Le tabelle con oggetti di grandi dimensioni possono anche aumentare l'IO in modo significativo per costruire i record per COUNT (*).


2
Secondo wiki.postgresql.org, COUNT(*)è la scelta migliore:If you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
orange80,

1

Non sono sicuro della migliore risposta per te. Tuttavia, questa discussione sembra offrire alcuni buoni suggerimenti: n http://postgresql.1045698.n5.nabble.com/count-performance-issue-td2067873.html

Una nota è che potresti implementare un TRIGGER per mantenere il conteggio delle righe in una tabella separata (se COUNT (*) verrebbe chiamato frequentemente dalle tue applicazioni).

Alcune delle risposte suggeriscono che questo è sintomatico di un database che non è stato aspirato abbastanza di recente (suggerendo che autovacuum è disabilitato sul tuo server o per quel database in particolare)?

Un altro suggerimento è simile a:

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

E qualcuno identificato come note di A. Kretschmer:

No. L'attuale implementazione dell'indice non contiene informazioni sulla visibilità delle righe all'interno della transazione corrente. È necessario eseguire la scansione dell'intera tabella di dati per ottenere se la riga corrente è visibile all'interno della transazione corrente.

... supportare il mio commento sulle autorizzazioni a livello di riga che rappresentano un problema di prestazioni.

La mia ricerca ha anche rivelato WikiVS: MySQL vs. PostgreSQL: COUNT (*) .

Puoi esaminare gli altri risultati che ho trovato utilizzando Google: postgresql count (*) performance

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.