Perché SELEZIONA * è molto più veloce della selezione di tutte le colonne (in un ordine di colonne diverso) per nome?


12

Su una tabella con colonne a, b, c, d, e, f, g, h, i, j, k ottengo:

select * from misty order by a limit 25;
Time: 302.068 ms

E:

select c,b,j,k,a,d,i,g,f,e,h from misty order by a limit 25;
Time: 1258.451 ms

C'è un modo per rendere la selezione per colonna più veloce?

Aggiornare:

Nessun indice su una tabella, uno appena creato

Ecco l'ESPLAIN ANALYZE, non sembra troppo utile:

explain analyze select * from misty order by a limit 25;

Limit  (cost=43994.40..43994.46 rows=25 width=190) (actual time=404.958..404.971 rows=25 loops=1)
->  Sort  (cost=43994.40..45731.11 rows=694686 width=190) (actual time=404.957..404.963 rows=25 loops=1)
     Sort Key: a
     Sort Method: top-N heapsort  Memory: 28kB
     ->  Seq Scan on misty  (cost=0.00..24390.86 rows=694686 width=190) (actual time=0.013..170.945 rows=694686 loops=1)
Total runtime: 405.019 ms
(6 rows)

E:

explain analyze select c,b,j,k,a,d,i,g,f,e,h from misty order by a limit 25;

Limit  (cost=43994.40..43994.46 rows=25 width=190) (actual time=1371.735..1371.745 rows=25 loops=1)
->  Sort  (cost=43994.40..45731.11 rows=694686 width=190) (actual time=1371.733..1371.736 rows=25 loops=1)
     Sort Key: a
     Sort Method: top-N heapsort  Memory: 28kB
     ->  Seq Scan on misty  (cost=0.00..24390.86 rows=694686 width=190) (actual time=0.015..516.355 rows=694686 loops=1)
Total runtime: 1371.797 ms
(6 rows)

La colonna è indicizzata? Puoi postare spiegare analizzare?
user_0

1
Devi stare attento facendo due selezioni di fila e confrontando i tempi. I dati nella cache sulla seconda query potrebbero tenere conto della differenza nei tempi.
Walter Mitty,

1
Vedo anche differenze, anche se non così pronunciate. La mia tabella ha righe = 514431 larghezza = 215 e ottengo circa 1,5 secondi per il select *caso e circa 2,2 secondi per la selezione con colonne elencate in un ordine diverso .
Colin 't Hart,

Se elenco tutte le colonne nello stesso ordine definito nella tabella, ottengo approssimativamente le stesse volte come se lo fossi select *.
Colin 't Hart,

2
Il titolo è fuorviante. La domanda è davvero perché la durata di un ordinamento dipende dall'ordine delle colonne di output.
Daniel Vérité,

Risposte:


12

Questo è stato pubblicato nella mailing list di pgsql-hackers e ho cercato di rispondere in breve lì. Sembra che l'elenco di destinazione (colonne specificate) corrisponda esattamente al descrittore di tupla della relazione, cioè sia in numero di colonne che in ordine, quindi la scansione sottostante può restituire una tupla che è direttamente consumabile dal nodo Ordinamento incluso. D'altra parte, se l'elenco di destinazione non corrisponde (nell'ordine o nel numero di colonne specificate), la scansione restituisce una forma di tuple che richiede la fase di preparazione dei dati di Sort per eseguire lavoro extra (convertire da un formato di tupla interno a il formato direttamente consumabile dal codice di ordinamento).

A proposito, '*' viene trasformato internamente in un elenco che (intuitivamente) corrisponde al descrittore di tupla della relazione.

MODIFICA: Se dai un'occhiata ai tempi attuali di Seq Scan di EXPLAIN ANALYZE, puoi vedere che è più di quello precedente. Ciò è accaduto perché la scansione ha eseguito un'ulteriore fase di proiezione (ovvero la conversione della tupla heap in un formato di valori interni [], nulls []). E poiché ciò è accaduto, il nodo Ordinamento superiore ha dovuto fare un lavoro extra nella sua inizializzazione dei dati, quella di riconvertirlo nel formato tupla che il passo di ordinamento effettivo comprende. Ciò è evidente dal costo di avvio dell'ordinamento. Ciò non accade nel primo caso. Cioè, sia la scansione restituisce la tupla così com'è che il passo di inizializzazione dell'ordinamento semplicemente la copia.


@ Colin'tHart, spero che abbia un senso.
amitlan,

Sì. Speravo che sarebbe stato possibile saltare quel passaggio o accorciarlo usando un po 'di "shuffle di puntatore", ma questa è una discussione per pgsql-hacker.
Colin 't Hart,

Potrebbero esserci alcuni miglioramenti all'orizzonte con il recente rilancio del lavoro di ordinamento delle colonne logiche.
amitlan,

Ci stavo già pensando e sperando così!
Colin 't Hart,

caro signore, se ho solo bisogno di alcune colonne invece di tutte, quale sarà più veloce? selezionare * o selezionare some_of_columns? Molte grazie.
sgon00,
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.