Довольно простой вопрос, возможно, где-то ответили, но я не могу сформировать правильный поисковый вопрос для Google ...
Влияет ли количество столбцов в конкретной таблице на производительность запроса при выполнении запросов к подмножеству этой таблицы?
Например, если таблица Foo имеет 20 столбцов, но мой запрос выбирает только 5 из этих столбцов, влияет ли наличие 20 (скажем, 10) столбцов на производительность запроса? Предположим для простоты, что все, что содержится в предложении WHERE, включено в эти 5 столбцов.
Я обеспокоен использованием буферного кэша Postgres в дополнение к дисковому кэшу операционной системы. Я очень плохо понимаю физический дизайн хранилища Postgres. Таблицы хранятся на нескольких страницах (по умолчанию 8 КБ на страницу), но я не совсем понимаю, как оттуда устроены кортежи. Достаточно ли умен PG, чтобы получать с диска только те данные, которые содержат эти 5 столбцов?
источник
Ответы:
Физическое хранилище для строк описано в документации по разметке страницы базы данных . Содержимое столбца для одной и той же строки хранится на одной и той же странице диска, за исключением заметного содержимого TOAST (слишком большого для размещения на странице). Содержимое извлекается последовательно в каждой строке, как объяснено:
В простейшем случае (без столбцов TOAST) postgres будет извлекать всю строку, даже если нужно несколько столбцов. Таким образом, в этом случае ответ «да», наличие большего количества столбцов может оказать явное неблагоприятное влияние на кэш-память буфера отходов, особенно если содержимое столбцов велико, хотя все еще находится ниже порога TOAST.
Теперь случай TOAST: когда отдельное поле превышает ~ 2 КБ, движок сохраняет содержимое поля в отдельной физической таблице. Он также вступает в игру, когда вся строка не помещается на странице (8 КБ по умолчанию): некоторые поля перемещаются в хранилище TOAST. Док говорит:
Содержимое TOAST не извлекается, когда оно явно не требуется, поэтому его влияние на общее количество извлекаемых страниц невелико (несколько байтов на столбец). Это объясняет результаты в ответе @ dezso.
Что касается записи, каждая строка со всеми ее столбцами полностью перезаписывается при каждом обновлении, независимо от того, какие столбцы изменены. Таким образом, наличие большего количества столбцов, очевидно, более затратно для записей.
источник
Ответ Даниэля фокусируется на стоимости чтения отдельных строк. В этом контексте: Помещение
NOT NULL
столбцов фиксированного размера в первую очередь в вашей таблице немного помогает. Помещение соответствующих столбцов первым (те, которые вы запрашиваете) немного помогает. Минимизация заполнения (из-за выравнивания данных), играя тетрис выравнивания с вашими столбцами, может немного помочь. Но самый важный эффект пока не упомянут, особенно для больших столов.Очевидно, что из-за дополнительных столбцов строка занимает больше места на диске, поэтому на одной странице данных умещается меньше строк (по умолчанию 8 КБ). Отдельные строки расположены на нескольких страницах. Механизм базы данных обычно должен извлекать целые страницы, а не отдельные строки . Не имеет значения, являются ли отдельные строки несколько меньше или больше - до тех пор, пока нужно прочитать одинаковое количество страниц.
Если запрос извлекает (относительно) небольшую часть большой таблицы, где строки распределены более или менее случайным образом по всей таблице, поддерживаемой индексом, это приведет к примерно одинаковому количеству чтений страниц, с небольшим вниманием в размер строки. Нерелевантные столбцы не будут сильно тормозить вас в таком (редком) случае.
Как правило, вы будете извлекать патчи или кластеры строк, которые были введены в последовательности или близости, и обмениваться страницами данных. Эти строки разбросаны из-за беспорядка, чтобы удовлетворить ваш запрос, нужно прочитать больше страниц на диске. Необходимость читать больше страниц, как правило, является наиболее важной причиной замедления запроса. И это самый важный фактор, почему нерелевантные столбцы замедляют ваши запросы.
Для больших баз данных обычно недостаточно оперативной памяти, чтобы хранить все это в кэш-памяти. Большие строки занимают больше кеша, больше конфликтов, меньше обращений к кешу, больше дискового ввода-вывода. А чтение с диска обычно намного дороже. Меньше так с SSD, но существенная разница остается. Это добавляет к вышеупомянутому пункту о чтениях страницы.
Это может иметь значение, а может и не иметь значения, если не относящиеся к делу столбцы имеют значение TOAST. Соответствующие столбцы также могут быть TOAST-ed, возвращая большую часть того же эффекта.
источник
Небольшой тест:
Ограничение запроса до первых 250 строк (
WHERE num <= 250
) приводит к 34,539 мс и 8,343 мс соответственно. Выбор всего, кромеlong_long_text
этого ограниченного набора, приводит к 18,432 мс. Это показывает, что с вашей точки зрения PG достаточно умен.источник