RizVN Login



SQL-запросы. Нужно ли перечислять конкретные поля в SELECT?

SQL-запросы. Нужно ли перечислять конкретные поля в SELECT?В рамках данной статьи про SQL-запросы, я расскажу вам про то, нужно ли перечислять конкретные поля в SELECT, а так же какие при этом могут быть нюансы.

Базы данных предоставляют массу полезных возможностей, для облегчения процесса написания sql-запросов. Однако, периодически их бездумное применение может весьма заметно сказываться на производительности и возникновении ошибок. Это же касается и оператора SELECT с возможностью получить все поля выборки, только указав символ * (звездочка).

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

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

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

Таблица продуктов:

product_idcat_idnamedesc
1 1 Продукт 1 Длинное описание
... ... ... Длинное описание
N X Продукт Z Длинное описание

Таблица категорий:

cat_idnamedesc
1 Категория 1 Длинное описание
... ... Длинное описание
Z Категория Z Длинное описание

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

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

-- Получим все поля сразу
select *
from `product` p
join `cat` c
on cat.cat_id = p.cat_id

Если вы запустите этот SELECT в админке БД, то никаких ошибок не появится и вы получите все товары с их категориями. Однако, если же вы попытаетесь использовать классы с динамическим присваиванием имен полей, например, в PHP, то возникнут проблемы. Дело в том, что колонки "name" и "desc" повторяются у таблиц. Это означает, что в результате при получении данных значения полей в том же PHP будут заменяться. К примеру, вместо описаний продуктов вы получите описания категорий.

Примечание: Стоит знать, что в зависимости от драйверов и типа БД, данный запрос может интерпретироваться по разному и так же результаты могут быть разными, но в большинстве своем они все будут приводить к ошибкам.

Если же вы перечислите поля и используете возможность указания названия полей в результатах SELECT, то с такой ошибкой вы не столкнетесь:

-- Получим нужные поля
select p.product_id, p.name, p.desc, c.cat_id, c.name as cat_name, c.desc as cat_desc
from `product` p
join `cat` c
on cat.cat_id = p.cat_id

Как видите, такой select запрос уже не приведет к проблемам на серверной стороне.

Примечание: Стоит понимать, что несмотря на то, что пример простой, в больших БД со сложной структурой такая мелочь может привести к существенным ошибкам.

Вторая ситуация. SQL-запросы для получения значений справочников. Каждый знаком с выпадающими списками. Чаще всего они используются в админках сайтов и, порой, во всяких формах обратной связи. Представим себе как раз ситуацию с некой формой, где вам нужно указывать отдельно товар и отдельно категорию. Чаще всего в такой ситуации используют два следующих запроса:

-- Получим все поля продукта
select * from `product`
-- Получим все поля категории
select * from `cat`

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

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

Дело в том, что используя оператор * (звездочка) в SELECT, вы говорите БД, чтобы она вытаскивала не только нужные вам данные (идентификатор и название), но и все описания. А это значит, что каждый запрос потребует дополнительного возвращать по 3 Мб данных (1000 * 3000). Т.е. для отображения формы вам нужно дополнительно формировать 6 Мб данных. Что же будет, если хотя бы сотня пользователей откроет вашу страничку? Правильно, вначале БД придется передавать веб-серверу, а затем веб-серверу придется передавать браузерам пользователей 600 Мб!!!! ненужных данных.

Примечание: Конечно, стоит знать, что БД предусматривают кэш запросов, ровно как и некоторые классы серверных приложений, однако на производительности это все равно сказывается.

Решается же эта проблема легко и элементарно:

-- Получим нужные поля продукта
select `product_id`, `name` from `product`
-- Получим нужные поля категории
select `cat_id`, `name` from `cat`

Вроде бы указали всего пару полей, но в такой ситуации, БД уже не будет передавать эти 6 Мб лишних данных и пользователи не будут наблюдать тормоза на сайте.

Как видите, используя возможности SQL-запросов, того же SELECT и * (звездочки), всегда стоит задумываться о здравом смысле.

1 1 1 1 1 1 1 1 1 1 Рейтинг 5.00 (2 Голосов)

Комментарии / отзывы   

0 # Столовкин 24.05.2017 13:13
Хм. Даже не задумывался о такой вещи. Весьма полезная статья
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору

Добавить комментарий / отзыв

Комментарий - это вежливое и наполненное смыслом сообщение (правила).


Введите защитный код

Обновить
Защитный код

Каталог программ