Почему SELECT * намного быстрее, чем выбор всех столбцов (в другом порядке столбцов) по имени?

12

На таблице со столбцами a, b, c, d, e, f, g, h, i, j, k я получаю:

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

И:

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

Есть ли способ сделать выбор по столбцу так быстро?

Обновить:

Нет индекса для таблицы, недавно созданной

Вот EXPLAIN ANALYZE, не кажется слишком полезным:

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)

И:

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)
Евгений
источник
Является ли столбец индексированным? Можете ли вы опубликовать объяснить анализ?
user_0
1
Вы должны быть осторожны, делая два выбора подряд и сравнивая время. Данные в кеше по второму запросу могут учитывать разницу во времени.
Уолтер Митти
1
Я также вижу различия, хотя и не такие явные. Моя таблица имеет строки = 514431 ширина = 215, и я получаю приблизительно 1,5 с для select *случая и приблизительно 2,2 с для выбора со столбцами, перечисленными в другом порядке .
Colin 't Hart
Если я перечислю все столбцы в том же порядке, как определено в таблице, я получу примерно такое же время, как если бы я select *.
Colin 't Hart
2
Название вводит в заблуждение. Вопрос в том, почему продолжительность сортировки зависит от порядка выходных столбцов.
Даниэль Верите

Ответы:

12

Это было опубликовано в списке рассылки pgsql-hackers, и я попытался ответить вкратце. Похоже, что если целевой список (указанные столбцы) точно соответствует дескриптору кортежа отношения, то есть как по количеству столбцов, так и по порядку, то базовое сканирование может вернуть кортеж, который непосредственно потребляется включающим узлом сортировки. С другой стороны, если целевой список не совпадает (либо по порядку, либо по количеству указанных столбцов), сканирование возвращает форму кортежей, для выполнения которой требуется этап подготовки данных Sort для выполнения дополнительной работы (преобразование из внутреннего формата кортежа в формат, непосредственно потребляемый кодом сортировки).

Кстати, '*' внутренне преобразуется в список, который (интуитивно) соответствует дескриптору кортежа отношения.

РЕДАКТИРОВАТЬ: Если вы посмотрите на фактическое время Seq Scan вашего EXPLAIN ANALYZE, вы увидите, что оно больше, чем прежнее. Это произошло из-за того, что сканирование выполнило дополнительный шаг проецирования (то есть преобразование набора кучи во внутренний формат values ​​[], nulls []). И поскольку это произошло, верхний узел сортировки должен был выполнить дополнительную работу по инициализации своих данных, то есть преобразовать его обратно в формат кортежа, который понимает действительный шаг сортировки. Это очевидно из стоимости запуска Сорта. Этого не происходит в первом случае. Таким образом, и сканирование возвращает кортеж как есть, и шаг инициализации сортировки просто копирует его.

amitlan
источник
@ Colin'tHart, надеюсь, это имеет смысл.
Амитлан
Да. Я бы надеялся, что можно было бы пропустить этот шаг или сделать его короче, используя некоторую «перетасовку указателя», но это обсуждение для pgsql-хакеров.
Colin 't Hart
На горизонте могут быть некоторые улучшения с недавним возрождением работы по упорядочению логических столбцов.
Амитлан
Я уже думал об этом и надеялся на это!
Colin 't Hart
Уважаемый сэр, если мне нужны только некоторые столбцы вместо всех, что будет быстрее? выберите * или выберите some_of_columns? Большое спасибо.
sgon00