Зміни схеми
- Отримати на замовлення --- Якщо код отримує стовпчик № як спосіб отримання даних, зміна схеми призведе до перенастроювання номерів стовпців. Це зіпсує додаток, і погані речі відбудуться.
- Отримати по імені --- Якщо код отримує стовпчик за назвою, наприклад
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);
Зміна на таблицю не порушила б ваші дані. Цей запит працює однаково перед зміною та після зміни.
Індексація
Коли ви робите, select * from
ви витягуєте всі рядки з усіх таблиць, які відповідають умовам. Навіть таблиці, які вас справді не цікавлять. Хоча це означає, що більше даних передається, є ще одна проблема з продуктивністю, яка ховається далі за стеком.
Покажчики. (пов'язано з SO: Як використовувати індекс у select операторі? )
Якщо ви відтягуєте багато стовпців, оптимізатор плану баз даних може ігнорувати, використовуючи індекс, тому що вам все одно доведеться діставати всі ці стовпці в будь-якому разі, і для цього знадобиться більше часу, щоб використовувати індекс, а потім отримати всі стовпці в запиті ніж було б просто зробити повне сканування таблиці.
Якщо ви просто вибираєте, скажімо, прізвище користувача (якого ви багато робите і тому на ньому є індекс), база даних може робити сканування лише з індексом ( postgres wiki index scan , myql full scan сканування vs full індексне сканування , сканування лише для індексів: уникнення доступу до таблиці ).
Існує досить багато оптимізацій щодо зчитування лише з індексів, якщо це можливо. Інформацію можна стягувати швидше на кожній сторінці покажчиків, тому що ви також тягнете її менше - ви не тягнете в усіх тих інших стовпцях для select *
. Можливе сканування лише з індексом, щоб швидше повертати результати на порядок у 100 разів (джерело: Вибрати * погано ).
Це не говорить про те, що повноцінне сканування індексів є чудовим, його все-таки повне сканування - але воно краще, ніж сканування повного столу. Як тільки ви почнете гнати за всіма способами, які select *
шкодять продуктивності, ви продовжуєте знаходити нові.
Пов'язане читання