Что быстрее / лучше? SELECT * или SELECT column1, colum2, column3 и т. Д. - PullRequest
151 голосов
/ 15 сентября 2008

Я слышал, что SELECT * - это, как правило, плохая практика при написании команд SQL, поскольку он более эффективен для SELECT столбцов, которые вам особенно нужны.

Если мне нужно SELECT каждый столбец в таблице, я должен использовать

SELECT * FROM TABLE

или

SELECT column1, colum2, column3, etc. FROM TABLE

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

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

ОБНОВЛЕНИЕ: Я, вероятно, должен указать, что единственная ситуация, когда я действительно хочу, чтобы сделал SELECT *, это когда я выбираю данные из одной таблицы, где я знаю все столбцы всегда нужно извлекать, даже когда добавляются новые столбцы.

Однако, учитывая ответы, которые я видел, это все равно кажется плохой идеей, и SELECT * никогда не следует использовать по гораздо более техническим причинам, чем я когда-либо думал.

Ответы [ 47 ]

156 голосов
/ 15 сентября 2008

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

Вот сообщение, которое я написал об этом: Реальная причина, по которой запросы на выбор - плохое покрытие индекса

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

57 голосов
/ 16 сентября 2008

Учитывая вашу спецификацию того, что вы выбираете все столбцы, в настоящее время есть небольшая разница . Поймите, однако, что схемы базы данных меняются. Если вы используете SELECT *, вы добавите в таблицу новые столбцы, хотя, по всей вероятности, ваш код не готов к использованию или представлению этих новых данных. Это означает, что вы подвергаете свою систему неожиданным изменениям производительности и функциональности.

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

  1. Чтение из базы данных
  2. Отправлено по сети
  3. Маршалл в вашем процессе
  4. (для технологий типа ADO) Сохранено в таблице данных в памяти
  5. Игнорируется и выбрасывается / сборщик мусора

Элемент № 1 имеет много скрытых затрат, в том числе устранение некоторого потенциального индекса покрытия, вызывая загрузки страниц данных (и перегрузку кэша сервера), вызывая блокировки строк / страниц / таблиц, которых в противном случае можно было бы избежать.

Соотнесите это с потенциальной экономией при указании столбцов с *, и единственная потенциальная экономия:

  1. Программисту не нужно пересматривать SQL для добавления столбцов
  2. Сетевой транспорт SQL меньше / быстрее
  3. Время анализа / проверки запроса SQL Server
  4. Кэш плана запросов SQL Server

Для пункта 1 реальность такова, что вы собираетесь добавить / изменить код, чтобы использовать любой новый столбец, который вы можете добавить в любом случае, так что это стирка.

Для пункта 2 разница редко бывает достаточной, чтобы подтолкнуть вас к другому размеру пакета или количеству сетевых пакетов. Если вы дойдете до того момента, когда преобладает проблема с передачей операторов SQL, вам, вероятно, сначала нужно уменьшить скорость операторов.

Для пункта 3 экономия НЕТ, так как расширение * должно произойти в любом случае, что означает, в любом случае, обращение к схеме таблиц. Реально, перечисление столбцов будет стоить одинаково, потому что они должны быть проверены по схеме. Другими словами, это полная стирка.

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

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

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

Мой совет: ВСЕГДА ВЫБИРАЙТЕ определенные столбцы . Помните, что вы хорошо разбираетесь в том, что делаете снова и снова, поэтому просто приобретайте привычку делать это правильно.

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

33 голосов
/ 04 июня 2010

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

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

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

30 голосов
/ 04 июня 2010

Есть четыре причины, по которым select * это плохо:

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

  2. Если имя столбца, которое вы используете, изменяется, лучше его поймать раньше (в момент вызова SQL), а не когда вы пытаетесь использовать столбец, который больше не существует (или уже имел его имя изменилось и т. д.)

  3. Перечисление имен столбцов делает ваш код намного более самодокументированным и, следовательно, более читабельным.

  4. Если вы переводите по сети (или даже если нет), столбцы, которые вам не нужны, просто напрасны.

9 голосов
/ 15 сентября 2008

Указание списка столбцов: обычно лучший вариант, потому что ваше приложение не будет затронуто, если кто-то добавит / вставит столбец в таблицу.

6 голосов
/ 22 сентября 2008

Указание имен столбцов определенно быстрее - для сервера. Но если

  1. производительность не является большой проблемой (например, это база данных контента веб-сайта с сотнями, может быть, тысячами - но не миллионами - строк в каждой таблице); И
  2. ваша задача состоит в том, чтобы создать множество небольших похожих приложений (например, общедоступные веб-сайты с управлением контентом), используя общую структуру, а не создавать сложное одноразовое приложение; И
  3. важна гибкость (множество настроек схемы БД для каждого сайта);

тогда вам лучше придерживаться SELECT *. В нашей среде интенсивное использование SELECT * позволяет нам вводить новое поле управляемого содержимого веб-сайта в таблицу, предоставляя ему все преимущества CMS (управление версиями, рабочий процесс / утверждения и т. Д.), При этом только касаясь кода на пара баллов, вместо пары десятков баллов.

Я знаю, что гуру БД возненавидят меня за это - продолжайте, проголосуйте за меня - но в моем мире время разработчиков ограничено, и циклов ЦП много, поэтому я соответствующим образом корректирую то, что я сохраняю и что я трачу.

6 голосов
/ 04 июня 2010

SELECT * - плохая практика, даже если запрос не передается по сети.

  1. Выбор большего количества данных, чем нужно, делает запрос менее эффективным - сервер должен считывать и передавать дополнительные данные, поэтому это требует времени и создает ненужную нагрузку на систему (не только сеть, как упоминалось другими, но и диск, Процессор и т. Д.). Кроме того, сервер не может оптимизировать запрос так, как мог бы (например, использовать индекс запроса для запроса).
  2. Через некоторое время структура вашей таблицы может измениться, поэтому SELECT * вернет другой набор столбцов. Таким образом, ваше приложение может получить набор данных неожиданной структуры и сломаться где-то вниз по течению. Явное указание столбцов гарантирует, что вы либо получите набор данных известной структуры, либо получите явную ошибку на уровне базы данных (например, «столбец не найден»).

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

4 голосов
/ 04 июня 2010

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

SELECT Field1, Field2 FROM SomeTable WHERE --(constraints)

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

4 голосов
/ 15 сентября 2008

С точки зрения производительности, SELECT с определенными столбцами может быть быстрее (не нужно читать все данные). Если ваш запрос действительно использует ВСЕ столбцы, SELECT с явными параметрами по-прежнему предпочтительнее. Любая разница в скорости будет в основном незаметной и почти постоянной. Однажды ваша схема изменится, и это хорошая страховка для предотвращения проблем из-за этого.

4 голосов
/ 04 июня 2010

Здесь уже дано много веских объяснений, вот еще одна, о которой не упоминалось.

Явное присвоение имен столбцам поможет вам в дальнейшем техническом обслуживании. В какой-то момент вы собираетесь внести изменения или устранить неполадки, и вы задаетесь вопросом: «Где, черт возьми, этот столбец используется».

Если у вас есть имена, перечисленные в явном виде, то найти каждую ссылку на этот столбец - через все ваши хранимые процедуры, представления и т. Д. - просто. Просто дамп сценария CREATE для вашей схемы БД и текстовый поиск по нему.

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