В SQL Server 2012 (или любой другой версии, начиная с 2005 г.) использование SELECT *...
является единственно возможной проблемой производительности в операторе SELECT верхнего уровня запроса.
Так что это не проблема в Views (*), в подзапросах, в предложениях EXIST, в CTE, и SELECT COUNT(*)..
т. Д. И т. Д. Обратите внимание, что это, вероятно, также верно для Oracle, DB2 и, возможно, PostGres (не уверен) , но очень вероятно, что это все еще проблема во многих случаях для MySql.
Чтобы понять, почему (и почему это все еще может быть проблемой в SELECT верхнего уровня), полезно понять, почему это когда-либо было проблемой, потому что использование SELECT *..
означает « вернуть ВСЕ столбцы ». В целом это вернет намного больше данных, чем вы действительно хотите, что, очевидно, может привести к гораздо большему количеству операций ввода-вывода, как на диске, так и в сети.
Менее очевидно то, что это также ограничивает то, какие индексы и планы запросов может использовать оптимизатор SQL, поскольку он знает, что в конечном итоге должен возвращать все столбцы данных. Если он может заранее знать, что вам нужны только определенные столбцы, он часто может использовать более эффективные планы запросов, используя преимущества индексов, которые имеют только эти столбцы. К счастью, есть способ узнать это заранее, чтобы вы явно указали нужные столбцы в списке столбцов. Но когда вы используете «*», вы отказываетесь от этого в пользу «просто дайте мне все, я выясню, что мне нужно».
Да, для обработки каждого столбца также требуется дополнительное использование ЦП и памяти, но это почти всегда незначительно по сравнению с этими двумя вещами: значительная дополнительная пропускная способность диска и сети, необходимая для столбцов, которые вам не нужны, и необходимость использовать меньше оптимизированный план запроса, потому что он должен включать каждый столбец.
Так что изменилось? По сути, оптимизаторы SQL успешно включили функцию под названием «Оптимизация столбцов», которая просто означает, что теперь они могут вычислять в подзапросах нижнего уровня, если вы когда-либо собираетесь использовать столбец на верхних уровнях запроса.
Результатом этого является то, что больше не имеет значения, если вы используете «SELECT * ..» на нижнем / внутреннем уровнях запроса. Вместо этого действительно важно то, что находится в списке столбцов SELECT верхнего уровня. Если вы не используете SELECT *..
верхнюю часть, то, опять же, вы должны предполагать, что вы хотите ВСЕ столбцы, и поэтому не можете эффективно использовать оптимизацию столбцов.
(* - обратите внимание, что существует другая, незначительная проблема привязки в представлениях, *
когда они не всегда регистрируют изменения в списках столбцов при использовании «*». Существуют другие способы решения этой проблемы, которые не влияют на производительность.)
Его физически и проблематично разрешено использовать
select * from table
, однако это плохая идея. Зачем?Прежде всего, вы обнаружите, что возвращаете ненужные столбцы (ресурсоемкие).
Во-вторых, для большой таблицы это займет больше времени, чем для именования столбцов, потому что когда вы выбираете *, вы фактически выбираете имена столбцов из базы данных и говорите: «дайте мне данные, связанные со столбцами, имена которых есть в этом другом списке». «. Хотя это быстро для программиста, представьте себе, что вы делаете такой поиск на компьютере банка, который может иметь буквально сотни тысяч поисков в минуту.
В-третьих, выполнение этого на самом деле усложняет работу разработчика. Как часто вам нужно переключаться между SSMS и VS, чтобы получить все имена столбцов?
В-четвертых, это признак ленивого программирования, и я не думаю, что какой-либо разработчик захочет эту репутацию.
источник
Это может быть проблемой, если вы поместите
Select * ...
код в программу, потому что, как указывалось ранее, база данных может со временем меняться и иметь больше столбцов, чем вы ожидали при написании запроса. Это может привести к сбою программы (в лучшем случае), или программа может пойти своим чередом и испортить некоторые данные, потому что просматривает значения полей, которые не были записаны для обработки. Короче говоря, производственный код должен ВСЕГДА указывать поля, которые будут возвращены вSELECT
.Сказав это, у меня меньше проблем, когда
Select *
является частьюEXISTS
предложения, так как все, что будет возвращено в программу, это логическое значение, указывающее успех или неудачу выбора. Другие могут не согласиться с этой позицией, и я уважаю их мнение по этому поводу. Код МОЖЕТ быть немного менее эффективным,Select *
чем код «Выбрать 1» вEXISTS
предложении, но я не думаю, что в любом случае существует опасность повреждения данных.источник
Много ответов, почему
select *
это не так, поэтому я расскажу, когда почувствую, что это правильно или, по крайней мере, ОК.1) В EXISTS содержимое части запроса SELECT игнорируется, поэтому вы можете даже написать,
SELECT 1/0
и это не приведет к ошибке.EXISTS
просто проверяет, что некоторые данные вернутся, и возвращает логическое значение, основанное на этом.2) Это может вызвать огненный шторм, но мне нравится использовать
select *
в своей истории триггеры. Таким образомselect *
, он не позволяет главной таблице получить новый столбец без добавления столбца в таблицу истории, а также из-за ошибки, возникающей сразу при вставке / обновлении / удалении в основную таблицу. Это предотвратило множество случаев, когда разработчики добавляли столбцы и забывали добавить их в таблицу истории.источник
SELECT 1
потому что он, очевидно, уведомляет будущих разработчиков кода о ваших намерениях. Это не является обязательным требованием , но если я... WHERE EXISTS (SELECT 1 ...)
это вижу, то, очевидно, объявляет себя тестом на правду.SELECT 1
миф о том, что производительность будет лучше, чемSELECT *
. Однако оба варианта вполне приемлемы. Там нет различий в производительности из-за того, как оптимизатор обрабатывает EXISTS. Нет никакой разницы в удобочитаемости из-за слова «СУЩЕСТВУЕТ», которое явно объявляет о проверке правды.Column8
к основной таблице, забывая таблицу истории. Разработчик пишет набор кода, реализованного в столбце 8. Затем он добавляетColumn9
в основную таблицу; на этот раз не забывая также добавить в историю. Позже при тестировании он понимает, что забыл добавитьColumn9
в историю (благодаря вашей технике обнаружения ошибок), и быстро добавляет ее. Теперь триггер, кажется, работает, но данные в столбцах 8 и 9 перепутаны в истории. : S