Наверняка многим известно, что SELECT * это плохо. Что это источник лишнего сетевого трафика и проблем с производительностью. Но с приходом SQL Azure за SELECT * приходится Платить в прямом смысле этого слова :) т.к. чем больше данных достаём из базы тем больше платим. Это ещё один довод в пользу того, чтобы не использовать SELECT * в своих проектах, и в этом посте я расскажу ещё о нескольких "прелестях" которые нам даёт использование * вместо перечисления списка столбцов в операторе SELECT.
Ненужный сетевой трафик
Наиболее яркая и сразу бросающаяся в глаза причина не использовать SELECT *. У меня прям сердце кровью обливается, когда вижу код, который тянет кучу столбцов, в то время как на самом деле используется лишь малая их часть. Например SELECT * для заполнения дропдауна, в котором нужны только Id и Name. Больше данных возвращаем –> больше нагрузка на сеть –> дольше выполняется запрос. А в SQL Azure ещё и больше платим.
Проблемы с производительностью
Вот это уже интересней. Здесь не всё так очевидно. Приведу пример. У нас есть табличка Users у которой 2 поля: Id и Name. По полю Id постороен кластерный индекс, по полю Name некластерный (IDX_USERS_NAME):
CREATE TABLE Users
(
Id int NOT NULL IDENTITY,
Name nvarchar(50) NOT NULL,
CONSTRAINT PK_USERS PRIMARY KEY(Id)
)
GO
CREATE INDEX IDX_USERS_NAME ON Users(Name)
GO
И вставляем немного тестовых данных:
INSERT INTO Users VALUES('Vasya')
GO 1000
INSERT INTO Users VALUES('Petya')
GO
Теперь делаем SELECT * и смотрим план запроса:
SELECT * FROM Users WHERE Name = 'Petya'
|
|
Здесь всё в порядке. Как и ожидалось выполняется поиск по некластерному индексу. Теперь добавим в таблицу новое поле и выполним тот же запрос:
ALTER TABLE Users ADD Email nvarchar(50) GO
SELECT * FROM Users WHERE Name = 'Petya'
|
|
План изменился. Мы получили ненужный Key Lookup и соответственно удар по производительности. Но это лишь небольшой пример. В других случаях можно получить более глобальные и совершенно непредсказуемые изменения плана запроса, которые скажутся на производительности вашего приложения.
И в заключение хочу сказать, что рецепт избавления от этих проблем довольно прост, и, скорее всего, уже известен вам – это перечисление списка столбцов в запросе. Да, это может быть порой неудобно, занимает больше времени, но не поленитесь :) преимущества перевешивают недостатки. И если в хранимках и просто в запросах нужно вместо звёздочки прописать список необходимых запросу столбцов, то LINQ to SQL и Entity Framework (и другие ORM-системы я подозреваю тоже) генерируют запросы с перечислением списка столбцов. Здесь желательно также перечислять список столбцов в .Select(…) для ограничения выборки.
Ссылки по теме:
- SELECT * AND SQL Azure
- Выражение SELECT
Денис Резник
.Net Team Lead at LPP Soft
Trainer at Microsoft Innovation Center
Харьков, Украина