Изменения схемы
- Выборка по порядку --- Если код выбирает номер столбца как способ получения данных, изменение в схеме приведет к перенастройке номеров столбцов. Это испортит приложение, и произойдут плохие вещи.
- Выборка по имени --- Если код выбирает столбец по имени, например
foo
, а другая таблица в запросе добавляет столбец foo
, то, как это обрабатывается, может вызвать проблемы при попытке получить правильный foo
столбец.
В любом случае, изменение схемы может вызвать проблемы с извлечением данных.
Далее рассмотрим, удаляется ли использованный столбец из таблицы. Все select * from ...
еще работает, но выдает ошибки при попытке извлечь данные из набора результатов. Если в запросе указан столбец, запрос выдаст ошибку, вместо этого дается четкое указание на то, в чем и где проблема.
Затраты на данные
С некоторыми столбцами может быть связано значительное количество данных. Выбор назад *
потянет все данные. Да, вот что varchar(4096)
на 1000 строк, которые вы выбрали, дает вам дополнительные 4 мегабайта данных, которые вам не нужны, но все равно отправляются по проводам.
В связи с изменением схемы, varchar может не существовать там, когда вы впервые создали таблицу, но теперь она там.
Неспособность передать намерение
Когда вы выбираете обратно *
и получаете 20 столбцов, но вам нужно только 2 из них, вы не передаете смысл кода. Глядя на запрос, который делает, select *
никто не знает, каковы его важные части. Могу ли я изменить запрос на использование этого другого плана, чтобы ускорить его, не включая эти столбцы? Я не знаю, потому что цель того, что возвращает запрос, не ясна.
Давайте посмотрим на некоторые скрипты SQL, в которых рассматриваются эти изменения схемы .
Во-первых, исходная база данных: http://sqlfiddle.com/#!2/a67dd/1
DDL:
create table one (oneid int, data int, twoid int);
create table two (twoid int, other int);
insert into one values (1, 42, 2);
insert into two values (2, 43);
SQL:
select * from one join two on (one.twoid = two.twoid);
И столбцы вы получаете обратно являются oneid=1
, data=42
, twoid=2
, и other=43
.
Что произойдет, если я добавлю столбец к первой таблице? http://sqlfiddle.com/#!2/cd0b0/1
alter table one add column other text;
update one set other = 'foo';
И мои результаты от того же самого запроса , как и раньше являются oneid=1
, data=42
, twoid=2
, и other=foo
.
Изменение в одной из таблиц нарушает значения a, select *
и внезапно ваша привязка 'other' к int приведет к ошибке, и вы не знаете почему.
Если вместо этого ваш оператор SQL был
select
one.oneid, one.data, two.twoid, two.other
from one join two on (one.twoid = two.twoid);
Изменение в таблице один не нарушило бы ваши данные. Этот запрос выполняется одинаково до изменения и после изменения.
индексирование
Когда вы делаете a, select * from
вы вытягиваете все строки из всех таблиц, которые соответствуют условиям. Даже таблицы, которые вам действительно безразличны. Хотя это означает, что передается больше данных, существует еще одна проблема с производительностью, которая скрывается в стеке.
Индексы. (связано с SO: Как использовать индекс в операторе выбора? )
Если вы извлекаете много столбцов, оптимизатор плана базы данных может игнорировать использование индекса, потому что вам все равно потребуется извлекать все эти столбцы, и потребуется больше времени, чтобы использовать индекс, а затем извлечь все столбцы в запросе. чем было бы просто сделать полное сканирование таблицы.
Если вы просто выбираете, скажем, фамилию пользователя (которую вы много делаете, и поэтому у вас есть индекс), база данных может выполнять сканирование только по индексу ( postgres wiki index only scan , mysql full table scan vs full сканирование индекса , индекс-Only Scan: Избежание таблицы Access ).
Существует довольно много оптимизаций относительно чтения только из индексов, если это возможно. Информация может быть получена быстрее на каждой странице индекса, потому что вы также извлекаете ее меньше - вы не используете все остальные столбцы для select *
. При сканировании только по индексу возможно возвращать результаты в 100 раз быстрее (источник: Select * is bad ).
Это не говорит о том, что полное индексное сканирование - это хорошо, это все же полное сканирование, но это лучше, чем полное сканирование таблицы. Как только вы начинаете преследовать все способы, которые select *
ухудшают производительность, вы продолжаете находить новые.
Связанное чтение