Zmiany schematu
- Pobierz według kolejności --- Jeśli kod pobiera kolumnę # jako sposób na uzyskanie danych, zmiana schematu spowoduje ponowne dostosowanie numerów kolumn. Spowoduje to zepsucie aplikacji i zdarzają się złe rzeczy.
- Pobierz według nazwy --- Jeśli kod pobiera kolumnę według nazwy, na przykład
foo
, a inna tabela w zapytaniu dodaje kolumnę foo
, sposób, w jaki jest ona obsługiwana, może powodować problemy przy próbie uzyskania właściwej foo
kolumny.
Tak czy inaczej zmiana schematu może powodować problemy z wyodrębnieniem danych.
Ponadto rozważ, czy używana kolumna została usunięta z tabeli. select * from ...
Nadal działa, ale błędy się, kiedy próbuje wyciągnąć dane z tabeli wynikowej. Jeśli kolumna jest podana w zapytaniu, zapytanie spowoduje błąd, dając wyraźne wskazanie, co i gdzie jest problem.
Obciążenie danych
Niektóre kolumny mogą być powiązane z dużą ilością danych. Wybranie z powrotem *
spowoduje pobranie wszystkich danych. Tak, oto varchar(4096)
to na 1000 wierszy, które wybrałeś z powrotem, dając ci dodatkowe 4 megabajty danych, których nie potrzebujesz, ale i tak są przesyłane przez sieć.
W związku ze zmianą schematu, ten varchar może nie istnieć tam, kiedy tworzyłeś tabelę po raz pierwszy, ale teraz ona tam jest.
Brak przekazania zamiaru
Gdy wybierzesz z powrotem *
i otrzymasz 20 kolumn, ale potrzebujesz tylko 2 z nich, nie przekazujesz zamiaru kodu. Patrząc na zapytanie, które select *
je wykonuje, nie wiadomo, jakie są jego ważne części. Czy mogę zmienić zapytanie, aby użyć tego innego planu, aby przyspieszyć, nie uwzględniając tych kolumn? Nie wiem, ponieważ cel tego, co zwraca zapytanie, nie jest jasny.
Przyjrzyjmy się niektórym skrzypkom SQL, które eksplorują nieco zmiany schematu .
Po pierwsze, początkowa baza danych: 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);
A kolumny wrócisz to oneid=1
, data=42
, twoid=2
, i other=43
.
Co się stanie, jeśli dodam kolumnę do tabeli pierwszej? http://sqlfiddle.com/#!2/cd0b0/1
alter table one add column other text;
update one set other = 'foo';
I moje wyniki z tego samego zapytania, jak wcześniej to oneid=1
, data=42
, twoid=2
, i other=foo
.
Zmiana w jednej z tabel zaburza wartości a select *
i nagle twoje powiązanie „innego” z int spowoduje zgłoszenie błędu i nie wiesz dlaczego.
Jeśli zamiast tego twoja instrukcja SQL była
select
one.oneid, one.data, two.twoid, two.other
from one join two on (one.twoid = two.twoid);
Zmiana w tabeli pierwszej nie zakłóciłaby danych. To zapytanie działa tak samo przed zmianą i po zmianie.
Indeksowanie
Kiedy robisz a select * from
, ciągniesz wszystkie wiersze z wszystkich tabel, które pasują do warunków. Nawet stoły, na których tak naprawdę nie zależy. Chociaż oznacza to, że przesyłanych jest więcej danych, w dalszej części stosu czai się inny problem z wydajnością.
Indeksy (powiązane z SO: Jak używać indeksu w instrukcji select? )
Jeśli wycofujesz wiele kolumn, optymalizator planu bazy danych może zignorować użycie indeksu, ponieważ i tak będziesz musiał pobrać wszystkie te kolumny, a użycie indeksu i pobranie wszystkich kolumn w zapytaniu zajęłoby więcej czasu. niż byłoby po prostu wykonać pełne skanowanie tabeli.
Jeśli po prostu wybierasz, powiedzmy, nazwisko użytkownika (które często robisz, a więc masz na nim indeks), baza danych może wykonać skanowanie tylko indeksu (skanowanie tylko indeksu postgres wiki , pełne skanowanie tabeli mysql vs pełne skanowania indeksu , indeksu Tylko scan: Unikanie tabeli programu Access ).
Jeśli jest to możliwe, istnieje sporo optymalizacji dotyczących odczytu tylko z indeksów. Informacje mogą być pobierane szybciej na każdej stronie indeksu, ponieważ również pobierasz mniej - nie pobierasz wszystkich innych kolumn dla select *
. Możliwe jest, że skanowanie tylko indeksu zwraca wyniki 100 razy szybciej (źródło: Wybierz * jest złe ).
Nie oznacza to, że pełne skanowanie indeksu jest świetne, nadal jest to pełne skanowanie - ale jest lepsze niż skanowanie pełnego stołu. Kiedy zaczniesz ścigać wszystkie sposoby, które select *
szkodzą wydajności, wciąż znajdujesz nowe.
Powiązane czytanie