Почему лучше использовать выборку по именам столбцов вместо select * в SQL?
Что проверяют
Знаете ли вы довод про план запроса, а не только про лишний трафик. Вопрос базовый, поэтому ответ уровня «передаётся больше данных» ждут от начинающего, а дальше смотрят, понимаете ли вы связь списка колонок с покрывающим индексом и то, как всё это выглядит со стороны ORM.
Как отвечать
Главный довод: покрывающий индекс. Если запрос просит только те колонки, которые лежат в индексе, сервер читает индекс и на этом заканчивает. Стоит дописать звёздочку, и на каждую найденную строку добавляется обращение к основной структуре таблицы, дешёвый поиск по индексу превращается в дорогой план, а заметно это становится только под нагрузкой.
Остальные доводы:
- широкие колонки, длинные тексты и двоичные данные тянутся по сети и материализуются в объекты;
- хрупкость к схеме: новая колонка молча попадает во все выборки, чтение по номеру позиции ломается, вставка из такой выборки перестаёт совпадать по типам;
- безопасность: хеш пароля или персональные данные уезжают в ответ API, потому что сущность сериализуется целиком.
Для C# добавьте слой ORM. Запрос LINQ без проекции материализует сущность полностью, то есть выбирает все колонки. Проекция в DTO через Select оставляет только нужные, а AsNoTracking снимает расходы на отслеживание изменений. В Dapper то же самое достигается явным списком колонок и типизированной моделью.
Назовите и исключения: звёздочка уместна в разовом разборе данных, а внутри exists и в count(*) список колонок вообще не материализуется, менять его там не на что.
Где спотыкаются
Останавливаются на трафике. Трафик заметен при выборке тысяч строк, а потеря покрывающего индекса бьёт по запросу, который возвращает одну строку, и именно он лежит на горячем пути.
Второе: считают вредным exists (select *) и верят, будто count(*) читает все колонки. Список внутри exists оптимизатор игнорирует, а count(*) считает строки, не разворачивая их.
Третье: думают, что LINQ сам выберет нужное. Без проекции загружается вся сущность, а вызов ToList до фильтра вытаскивает таблицу в память и фильтрует уже там. Явный список колонок рядом с забытой цепочкой Include даёт тот же эффект, что и звёздочка.