Чому 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 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)

Чи стовпчик індексований? Чи можете ви опублікувати пояснення аналізу?
користувач_0

1
Вам потрібно бути обережним, роблячи два варіанти підряд і порівнюючи час. Дані в кеші другого запиту можуть враховувати різницю в часі.
Вальтер Мітті

1
Я бачу також відмінності, хоча і не такі яскраво виражені. Моя таблиця має рядки = 514431 ширина = 215, і я отримую select *приблизно 1,5 секунди для корпусу та приблизно 2,2 секунди для вибору зі стовпцями, переліченими в іншому порядку .
Colin 't Hart

Якщо я перерахую всі стовпці в тому ж порядку, як визначено в таблиці, я отримаю приблизно те саме, що і я select *.
Колін 'Харт

2
Назва вводить в оману. Питання справді полягає в тому, чому тривалість сортування залежить від порядку вихідних стовпців.
Даніель Верете

Відповіді:


12

Це було розміщено у списку розсилки pgsql-хакерів, і я спробував там коротко відповісти. Здається, якщо цільовий список (вказані стовпці) точно відповідає дескриптору кортежу відношення, тобто як за кількістю стовпців, так і за порядком, тоді базове сканування може повернути кортеж, який безпосередньо споживається вкладеним вузлом Сортування. З іншого боку, якщо цільовий список не збігається (ні за порядком, ні за кількістю вказаних стовпців), сканування повертає форму кортежів, що вимагає кроку підготовки даних Sort для виконання додаткової роботи (перетворити з внутрішнього формату кортежу в формат, безпосередньо спожитий кодом сортування).

До речі, "*" внутрішньо перетворюється на список, який (інтуїтивно) відповідає дескриптору кортежу відносин.

EDIT: Якщо ви подивитесь на фактичний час останнього ПОЯСНЕННЯ АНАЛІЗУ, ви можете побачити, що це більше, ніж колишній. Це сталося тому, що сканування виконало додатковий крок проекції (тобто перетворення кортежу купи у внутрішні значення [], нульовий [] формат). А оскільки це сталося, верхній вузол Сортування повинен був зробити додаткову роботу при його ініціалізації даних, перетворенні його у формат кортежу, який розуміє власне крок сортування. Це видно з вартості запуску Sort. У першому випадку цього не відбувається. Тобто, і сканування повертає кортеж таким, яким він є, і етап ініціалізації сортування просто копіює його.


@ Colin'tHart, сподіваюся, що це має сенс.
amitlan

Так. Я би сподівався, що можна пропустити цей крок або зробити його коротшим, використовуючи якийсь "перетасовування покажчика", але це обговорення для pgsql-хакерів.
Colin 't Hart

На недавньому відродженні роботи з впорядкування логічних стовпців на горизонті можуть бути деякі покращення .
амітлан

Я вже про це думав і сподівався!
Colin 't Hart

шановний пане, якщо мені потрібні лише колонки замість усіх, що буде швидше? виберіть * або виберіть кілька_колонків? Дуже дякую.
sgon00
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.