Влияет ли количество возвращаемых столбцов на скорость запроса? - PullRequest
8 голосов
/ 12 мая 2009

Если у меня есть два запроса

SELECT Id, Forename, Surname
FROM Person
WHERE PersonName Like(‘%frank%’)

И

SELECT *
FROM Person
WHERE PersonName Like(‘%frank%’)

Какой запрос будет выполняться быстрее? Является ли условие / таблица присоединения наибольшим фактором или число возвращаемых столбцов?

Я спрашиваю, потому что я строю серию объектов, которые отображаются в таблицы базы данных. Обычно каждый объект будет иметь по крайней мере эти три метода:

Select - выбирает все

List - Выбирает достаточно для заполнения выпадающего списка

Search - Выбирает все, что отображается в результатах, обычно около 6 или около того столбцов.

Если каждый запрос возвращает один и тот же набор столбцов, обслуживание и тестирование кода должны быть более тривиальными. База данных вряд ли получит более 50000 строк в любой данной таблице, поэтому, если разница в производительности невелика, я возьму на себя экономию времени на разработку. Если производительность будет падать сквозь пол, я буду работать под другим углом.

Итак, для простоты разработки, SELECT * разумно или наивно?

Ответы [ 18 ]

25 голосов
/ 12 мая 2009

Вам лучше избегать SELECT *

  • Это приводит к путанице при изменении макета таблицы.
  • Он выбирает ненужные столбцы, и ваши пакеты данных становятся больше.
  • Столбцы могут получать повторяющиеся имена, что также не подходит для некоторых приложений.
  • Если все столбцы, которые вам нужны, охватываются индексом, SELECT columns будет использовать только этот индекс, тогда как SELECT * потребуется посетить записи таблицы, чтобы получить значения, которые вам не нужны. Также плохо для производительности.
7 голосов
/ 12 мая 2009

SELECT * обычно никогда не бывает хорошей идеей. Это может не замедлить вашу выборку СУБД, но, вероятно, приведет к тому, что по сети будет передаваться больше данных, чем вам нужно.

Тем не менее, это может быть сведено на нет незначительным использованием условия LIKE '%frank%', которое в основном не индексируется и приведет к полному сканированию таблицы.

Возможно, вы захотите очистить данные при их поступлении в базу данных, поскольку это почти наверняка сделает последующие запросы намного быстрее.

Если вам нужен откровенный ответ, убедитесь, что он хранится как откровенный, и используйте:

select x,y,z from table where name = 'frank'

Если вы также хотите получить Франклин, используйте:

select x,y,z from table where name like 'frank%'

Оба из них смогут использовать индекс для столбца имени, "%frank%" не будет.

5 голосов
/ 12 мая 2009

Я собираюсь пойти против течения здесь и сказать, что вы должны пойти с выбором *. Я думаю, что преждевременная оптимизация является корнем многих проблем, и вы вполне можете обнаружить, что она не влияет на вашу производительность, когда вы переходите к реальному использованию. Конечно, по книге это медленнее, должно быть, но это не значит, что разница важна на практике.

Однако следует помнить, что некоторые механизмы SQL (наверняка, MS-SQL) будут кэшировать select *, поэтому, если вы используете подготовленный оператор или представление или хранимую процедуру, которая его имеет, и изменяете Схема таблицы не изменится до тех пор, пока представление или sp не будут перекомпилированы, так что это хороший повод избегать этого, если вы не выполняете эти запросы динамически.

И, конечно, это зависит от ядра базы данных, поэтому небольшое нагрузочное тестирование было бы для того, чтобы убедиться, что попадание явно не велико.

2 голосов
/ 12 мая 2009

Для небольших проектов вы обычно можете выбрать select *. Это "правильно" не делать этого, хотя. Вы не заметите заметной разницы в скорости для одной таблицы в неиндексированном запросе ... единственное, что вы заметно делаете, это использование большей пропускной способности для столбцов, которые вы не читаете.

Тем не менее, вы заметите разницу в запросах только для индекса, когда вы нажимаете полную таблицу, когда вам нужно только попасть в индекс. Это особенно актуально, когда вы делаете соединения.

Select * действительно имеет применение, и если вы используете его правильно (скажем, в сочетании с кешем, убедитесь, что оно select table.* и обращаетесь к результатам по имени столбца), вы можете уменьшить количество запросов, сделанных вашим приложением. 1008 *

2 голосов
/ 12 мая 2009

Независимо от проблем с производительностью, рекомендуется всегда перечислять все поля в ваших запросах.

  • Что если вы решите добавить в будущем столбец TEXT или BLOB, который будет использоваться для определенного запроса? Ваш SELECT * вернет дополнительные данные независимо от того, нужны они вам или нет.
  • Что если вы переименуете столбец? Ваш SELECT * всегда будет работать, но проверяющий код будет сломан.
1 голос
/ 12 мая 2009

Количество столбцов в таблице не влияет на производительность вашего запроса. Количество столбцов, оперируемых в запросе, будет.

Обратите внимание на следующий пример из руководства по концепциям Oracle:

Формат строки и размер Oracle хранит каждый строка таблицы базы данных, содержащая данные для менее чем 256 столбцов как один или более строк Если целый ряд может быть вставлен в один данные блок, затем Oracle сохраняет строку как один ряд кусок. Тем не менее, если все данные строки не могут быть вставлены в один блок данных или если обновление существующая строка вызывает строку перерасти свой блок данных, затем Oracle сохраняет строку, используя несколько строк куски. Блок данных обычно содержит только один кусок строки для каждого ряда. когда Oracle должен хранить строку в более чем один ряд, он прикован несколько блоков.

Когда в таблице больше 255 столбцы, строки, которые имеют данные после 255-й столбец, вероятно, будет прикован в том же блоке. Это называется внутриблочная цепочка. Цепной ряд части соединены вместе, используя Гребные части. С внутриблочным цепочка, пользователи получают все данные в том же блоке. Если строка вписывается блок, пользователи не видят эффекта в производительности ввода-вывода, потому что нет лишних Операция ввода / вывода требуется для получения остальная часть ряда.

ОДНАКО: если есть 400 столбцов, я Держу пари, что большинство строк не подойдет в одном блоке, и, следовательно, вы увидите намного больше 'последовательное чтение файла БД' чем обычно требуется. А я помните, что Стив Адамс (или кто-то давно) упомянув, что есть дополнительная плата за доступ к колонке "дальше вниз по списку" - извините, не есть эта ссылка.

1 голос
/ 12 мая 2009

Если помните правильно из колледжа (и это было некоторое время), выбор * не является предпочтительным, но не так уж и плохо - пока вы не начнете присоединяться. Когда вы попадаете в реляционную алебру создания соединяемых кортежей, каждый столбец увеличивает время, поэтому я бы определенно избегал его, если это возможно.

0 голосов
/ 12 мая 2009

единственный раз, когда я использую "select *", на самом деле не событие "select *"

в частности:

select count(*) from table

это не то же самое, что

select count(ID) from table

первый возвращает количество строк в таблице
но вторая возвращает количество строк со значением NOT NULL ID.

тонкое различие, но стоит помнить.

0 голосов
/ 12 мая 2009

Это правильный путь и самый оптимальный. Причина в том, что вы собираете только необходимые данные, поэтому они занимают правильное пространство (что вам нужно) для хранения данных, прежде чем вы получите результаты.

SELECT Id, Forename, Surname
FROM Person
WHERE PersonName Like(‘%frank%’)

Это неверно, так как занимает неиспользуемые поля, которые занимают больше места для выполнения запроса, что замедляет результаты. Даже если вам повезет и вы используете все поля в своем запросе, лучше перечислить их по отдельности. Это уточнит запрос и какие данные должны быть возвращены любому другому разработчику, которому может потребоваться изменить запрос в будущем.

SELECT *
FROM Person
WHERE PersonName Like(‘%frank%’)
0 голосов
/ 12 мая 2009

Конечно. Лучше назовите столбцы, которые вы хотите получить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...