Что быстрее/лучше? SELECT * или SELECT column1, colum2, column3 и т.д.

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

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

SELECT * FROM TABLE

или

SELECT column1, colum2, column3, etc. FROM TABLE

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

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

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

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

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

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

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

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

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

Ответ 5

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

Ответ 6

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

  • производительность не является большой проблемой (например, это база данных контента сайта с сотнями, а может быть, тысячами, но не миллионами строк в каждой таблице); И
  • Ваша задача - создать множество небольших похожих приложений (например, веб-сайты, управляемые сайтом, ориентированные на общественность) с использованием общей структуры, а не создавать комплексное одноразовое приложение; И
  • важна гибкость (большое количество настроек схемы db для каждого сайта);

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

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

Ответ 7

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

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

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

Ответ 8

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

Ответ 9

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

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

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

Ответ 10

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

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

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

Ответ 11

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

Ответ 12

Всегда лучше указывать нужные столбцы, если вы думаете об этом один раз, SQL не должен думать "wtf is *" каждый раз, когда вы запрашиваете. Кроме того, кто-то позже может добавить столбцы в таблицу, которые вам действительно не нужны в вашем запросе, и вам будет лучше в этом случае указать все ваши столбцы.

Ответ 13

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

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

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

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

Ответ 14

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

Итак, если вы используете все данные, попробуйте SELECT * для простоты (представьте, что у вас много столбцов, а запрос JOIN... может стать ужасным). Тогда - измерить. Сравните с запросом имена столбцов, указанные явно.

Не спекулируйте о производительности, измерьте это!

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

Ответ 15

Выбор одинаково эффективен (с точки зрения скорости), если вы используете * или столбцы.

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

Что имеет значение с точки зрения производительности, это план экзекуции, который, в свою очередь, сильно зависит от вашего предложения WHERE и количества JOIN, OUTER JOIN и т.д.

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

Ответ 16

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

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

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

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

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

Ответ 17

Результат слишком велик. Он медленно генерирует и отправляет результат от механизма SQL клиенту.

Клиентская сторона, являющаяся общей программной средой, не должна и не должна быть предназначена для фильтрации и обработки результатов (например, предложение WHERE, предложение ORDER), поскольку количество строк может быть огромным (например, десятки миллионов строки).

Ответ 18

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

Ответ 19

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

Ответ 20

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

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

Что касается того, что быстрее, я буду откладывать на другие свои знания.

Ответ 21

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

Это также зависит от объема данных, которые вы хотите передать с сервера. Если один из столбцов определен как memo, graphic, blob и т.д., И вам не нужен этот столбец, вам лучше не использовать "Select *", или вы получите целую кучу данных, которые вы не используете хотите, и ваша производительность может пострадать.

Ответ 22

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

Ответ 23

SELECT * необходим, если требуется получить метаданные, такие как количество столбцов.

Ответ 24

Что все сказали выше, плюс:

Если вы стремитесь к удобочитаемому поддерживаемому коду, выполните следующее:

SELECT foo, bar FROM widgets;

мгновенно читается и показывает намерение. Если вы сделаете этот звонок, вы знаете, о чем вы возвращаетесь. Если у виджета есть только столбцы foo и bar, то выбор * означает, что вам все равно нужно подумать о том, что вы возвращаете, подтвердите правильность сопоставления заказа и т.д. Однако, если виджеты имеют больше столбцов, но вас интересует только foo и бар, тогда ваш код становится беспорядочным, когда вы запрашиваете подстановочный знак, а затем используете только то, что было возвращено.

Ответ 25

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

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

Ответ 26

Абсолютно определите столбцы, которые вы хотите ВЫБРАТЬ каждый раз. Нет причин не делать этого, и улучшение производительности стоит того.

Они никогда не должны иметь возможность "SELECT *"

Ответ 27

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

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

Ответ 28

В плане эффективности исполнения я не знаю какой-либо существенной разницы. Но для эффективности программистов я бы написал имена полей, потому что

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

Ответ 29

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

В конечном итоге лучшим планом является выбор конкретных столбцов.

Ответ 30

Также помните об изменениях. Сегодня Select * выбирает только те столбцы, которые вам нужны, но завтра он может также выбрать этот столбец varbinary (MAX), который я только что добавил, не сообщая вам, и теперь вы также возвращаете все 3,18 гигабайта двоичных данных, которые не были вчера в таблице.