За SELECT * приходится платить

        Наверняка многим известно, что 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'

 



image

Здесь всё в порядке. Как и ожидалось выполняется поиск по некластерному индексу. Теперь добавим в таблицу новое поле и выполним тот же запрос:

 


ALTER TABLE Users
ADD Email nvarchar(50)
GO


SELECT * FROM Users
WHERE Name = 'Petya'



image

План изменился. Мы получили ненужный Key Lookup и соответственно удар по производительности. Но это лишь небольшой пример. В других случаях можно получить более глобальные и совершенно непредсказуемые изменения плана запроса, которые скажутся на производительности вашего приложения.

        И в заключение хочу сказать, что рецепт избавления от этих проблем довольно прост, и, скорее всего, уже известен вам – это перечисление списка столбцов в запросе. Да, это может быть порой неудобно, занимает больше времени, но не поленитесь :) преимущества перевешивают недостатки. И если в хранимках и просто в запросах нужно вместо звёздочки прописать список необходимых запросу столбцов, то LINQ to SQL и Entity Framework (и другие ORM-системы я подозреваю тоже) генерируют запросы с перечислением списка столбцов. Здесь желательно также перечислять список столбцов в .Select(…) для ограничения выборки.

Ссылки по теме:

- SELECT * AND SQL Azure

- Выражение SELECT

 

photo of Денис РезникДенис Резник
.Net Team Lead at LPP Soft
Trainer at Microsoft Innovation Center
Харьков, Украина
 

photo of Денис Резник

blog comments powered by Disqus

Обо мне

MVP

Data Architect at Intapp, Inc.

PASS Regional Mentor, CEE

MCT, MCITP, MCPD, MCTS


Microsoft MVP

Month List