Słyszałem, że SELECT *
ogólnie jest to zła praktyka podczas pisania poleceń SQL, ponieważ jest bardziej wydajna w przypadku SELECT
kolumn, których potrzebujesz.
Jeśli potrzebuję SELECT
każdej kolumny w tabeli, powinienem użyć
SELECT * FROM TABLE
lub
SELECT column1, colum2, column3, etc. FROM TABLE
Czy wydajność naprawdę ma znaczenie w tym przypadku? Myślę, że SELECT *
byłoby bardziej optymalne wewnętrznie, gdybyś naprawdę potrzebował wszystkich danych, ale mówię to bez prawdziwego zrozumienia bazy danych.
Ciekawi mnie, jaka jest najlepsza praktyka w tym przypadku.
AKTUALIZACJA: Prawdopodobnie powinienem określić, że jedyną sytuacją, w której naprawdę chciałbym to zrobić, SELECT *
jest wybranie danych z jednej tabeli, o której wiem, że wszystkie kolumny będą zawsze musiały zostać pobrane, nawet gdy zostaną dodane nowe kolumny.
Biorąc jednak pod uwagę odpowiedzi, które widziałem, nadal wydaje się to złym pomysłem i SELECT *
nigdy nie powinno być używane z dużo bardziej technicznych powodów, o których myślałem.
Odpowiedzi:
Jednym z powodów, dla których wybranie określonych kolumn jest lepsze, jest to, że zwiększa prawdopodobieństwo, że SQL Server może uzyskać dostęp do danych z indeksów, zamiast odpytywania danych tabeli.
Oto post, który o tym napisałem: Prawdziwym powodem zapytań wybierających jest złe pokrycie indeksu
Jest również mniej kruchy do zmiany, ponieważ każdy kod, który zużywa dane, będzie miał taką samą strukturę danych, niezależnie od zmian wprowadzonych w schemacie tabeli w przyszłości.
źródło
vs
all_column_names), skoro mamy tysiące wierszy i wykonujemy polecenie SELECT z indeksem (w klauzuli WHERE)?Biorąc swoją specyfikację, które są wybierając wszystkie kolumny, nie ma różnicy w tym czasie . Pamiętaj jednak, że schematy bazy danych się zmieniają. Jeśli użyjesz
SELECT *
, dostaniesz jakiekolwiek nowe kolumny dodane do tabeli, nawet jeśli najprawdopodobniej twój kod nie jest przygotowany do używania lub prezentowania tych nowych danych. Oznacza to, że narażasz swój system na nieoczekiwane zmiany wydajności i funkcjonalności.Możesz chcieć odrzucić to jako niewielki koszt, ale pamiętaj, że kolumny, których nadal nie potrzebujesz, muszą zawierać:
Pozycja nr 1 wiąże się z wieloma ukrytymi kosztami, w tym wyeliminowaniem potencjalnego indeksu, powodując ładowanie stron danych (i niszczenie pamięci podręcznej serwera), generowanie blokad wierszy / stron / tabel, których można by uniknąć w inny sposób.
Zrównoważyć to z potencjalnymi oszczędnościami wynikającymi z określenia kolumn w porównaniu z,
*
a jedyne potencjalne oszczędności to:W przypadku pozycji 1 rzeczywistość jest taka, że zamierzasz dodać / zmienić kod, aby użyć dowolnej nowej kolumny, którą i tak możesz dodać, więc jest to pranie.
W przypadku punktu 2 różnica rzadko jest na tyle duża, aby popchnąć Cię do innego rozmiaru pakietu lub liczby pakietów sieciowych. Jeśli dojdziesz do momentu, w którym czas transmisji instrukcji SQL jest dominującym problemem, prawdopodobnie musisz najpierw zmniejszyć szybkość instrukcji.
W przypadku pozycji 3 NIE ma żadnych oszczędności, ponieważ rozszerzenie
*
tabeli i tak musi nastąpić, co i tak oznacza sprawdzenie schematu tabeli (ów). Realistycznie, umieszczenie kolumn na liście będzie wiązało się z tym samym kosztem, ponieważ muszą zostać sprawdzone pod kątem schematu. Innymi słowy, jest to pełne mycie.W przypadku pozycji 4, kiedy określisz konkretne kolumny, pamięć podręczna planu zapytań może się zwiększyć, ale tylko wtedy, gdy masz do czynienia z różnymi zestawami kolumn (co nie jest tym, co określono). W takim przypadku chcesz mieć różne wpisy w pamięci podręcznej, ponieważ potrzebujesz różnych planów w razie potrzeby.
Tak więc wszystko sprowadza się, ze względu na sposób, w jaki określiłeś pytanie, do odporności na problemy w obliczu ewentualnych modyfikacji schematu. Jeśli nagrywasz ten schemat do ROM (zdarza się), to jest
*
to całkowicie akceptowalne.Jednak moją ogólną wskazówką jest to, że powinieneś wybierać tylko te kolumny, których potrzebujesz, co oznacza, że czasami będzie wyglądać tak, jakbyś prosił o wszystkie z nich, ale bazy danych i ewolucja schematu oznaczają, że mogą pojawić się nowe kolumny, które mogą znacznie wpłynąć na zapytanie .
Moja rada jest taka, że ZAWSZE WYBIERAJ określone kolumny . Pamiętaj, że w tym, co robisz, stajesz się dobry, więc po prostu zdobądź nawyk robienia tego dobrze.
Jeśli zastanawiasz się, dlaczego schemat może się zmienić bez zmiany kodu, pomyśl w kategoriach rejestrowania audytu, dat wejścia w życie / wygaśnięcia i innych podobnych rzeczy, które są dodawane przez administratorów baz danych w celu systemowego rozwiązywania problemów ze zgodnością. Innym źródłem podstępnych zmian są denormalizacje wydajności w innym miejscu systemu lub w polach zdefiniowanych przez użytkownika.
źródło
Powinieneś wybrać tylko te kolumny, których potrzebujesz. Nawet jeśli potrzebujesz wszystkich kolumn, nadal lepiej jest podać nazwy kolumn, aby serwer sql nie musiał odpytywać tabeli systemowej o kolumny.
Ponadto aplikacja może się zepsuć, jeśli ktoś doda kolumny do tabeli. Twój program otrzyma kolumny, których też się nie spodziewał i może nie wiedzieć, jak je przetworzyć.
Poza tym, jeśli tabela ma kolumnę binarną, zapytanie będzie znacznie wolniejsze i zużyje więcej zasobów sieciowych.
źródło
Istnieją cztery ważne powody, dla których
select *
jest źle:Najważniejszym praktycznym powodem jest to, że zmusza użytkownika do magicznego poznania kolejności, w jakiej kolumny zostaną zwrócone. Lepiej być wyraźnym, co również chroni przed zmianą stołu, który ładnie przechodzi w ...
Jeśli nazwa kolumny, której używasz, ulegnie zmianie, lepiej jest ją wychwycić wcześnie (w momencie wywołania SQL), niż gdy próbujesz użyć kolumny, która już nie istnieje (lub zmieniła jej nazwę itp.) )
Podanie nazw kolumn sprawia, że kod jest znacznie bardziej samodokumentowany, a więc prawdopodobnie bardziej czytelny.
Jeśli przenosisz się przez sieć (lub nawet jeśli nie jesteś), kolumny, których nie potrzebujesz, są po prostu marnotrawstwem.
źródło
*
nazwę na zestaw).Określenie listy kolumn jest zwykle najlepszą opcją, ponieważ nie będzie to miało wpływu na aplikację, jeśli ktoś doda / wstawi kolumnę do tabeli.
źródło
Określanie nazw kolumn jest zdecydowanie szybsze - dla serwera. Ale jeśli
wtedy lepiej będzie trzymać się SELECT *. W naszym frameworku intensywne użycie SELECT * pozwala nam wprowadzić do tabeli nowe pole treści zarządzanej przez stronę internetową, dając mu wszystkie zalety CMS (wersjonowanie, przepływ pracy / zatwierdzenia itp.), Jednocześnie dotykając kodu tylko w kilka punktów zamiast kilkudziesięciu.
Wiem, że guru DB mnie za to nienawidzą - śmiało, głosuj na mnie - ale w moim świecie czas programisty jest ograniczony, a cykle procesora są obfite, więc odpowiednio dostosowuję to, co oszczędzam, a co marnuję.
źródło
SELECT * to zła praktyka, nawet jeśli zapytanie nie jest wysyłane przez sieć.
Oczywiście wszystko to nie ma większego znaczenia dla małego i prostego systemu.
źródło
Jeśli chodzi o wydajność, SELECT z określonymi kolumnami może być szybszy (nie ma potrzeby wczytywania wszystkich danych). Jeśli zapytanie naprawdę używa WSZYSTKICH kolumn, nadal preferowane jest polecenie SELECT z jawnymi parametrami. Każda różnica prędkości będzie w zasadzie niezauważalna i zbliżona do stałego czasu. Pewnego dnia twój schemat się zmieni i jest to dobre zabezpieczenie, aby zapobiec problemom z tego powodu.
źródło
Odpowiedziałem tutaj na wiele dobrych powodów, oto kolejny, o którym nie wspomniano.
Jawne nazwanie kolumn pomoże Ci w późniejszych pracach konserwacyjnych. W pewnym momencie będziesz wprowadzać zmiany lub rozwiązywać problemy i zaczniesz pytać „gdzie do cholery jest używana ta kolumna”.
Jeśli masz nazwy wymienione jawnie, znalezienie każdego odwołania do tej kolumny - poprzez wszystkie procedury składowane, widoki itp. - jest proste. Po prostu zrzuć skrypt CREATE dla swojego schematu bazy danych i przeszukaj go tekstowo.
źródło
zdecydowanie definiując kolumny, ponieważ SQL Server nie będzie musiał wyszukiwać kolumn, aby je wyciągnąć. Jeśli zdefiniujesz kolumny, SQL może pominąć ten krok.
źródło
Zawsze lepiej jest określić potrzebne kolumny, jeśli pomyślisz o tym raz, SQL nie musi myśleć „wtf is *” za każdym razem, gdy wykonujesz zapytanie. Co więcej, ktoś później może dodać kolumny do tabeli, których w rzeczywistości nie potrzebujesz w zapytaniu, a w takim przypadku będzie lepiej, określając wszystkie kolumny.
źródło
Problem z „select *” polega na możliwości przeniesienia danych, których tak naprawdę nie potrzebujesz. Podczas rzeczywistego zapytania do bazy danych wybrane kolumny tak naprawdę nie są uwzględniane w obliczeniach. Naprawdę „ciężki” jest transport danych z powrotem do klienta, a każda kolumna, której tak naprawdę nie potrzebujesz, marnuje przepustowość sieci i wydłuża czas oczekiwania na zwrot zapytania.
Nawet jeśli używasz wszystkich kolumn pobranych z „select * ...”, to na razie. Jeśli w przyszłości zmienisz układ tabeli / widoku i dodasz więcej kolumn, zaczniesz wprowadzać je do wybranych, nawet jeśli ich nie potrzebujesz.
Innym punktem, w którym instrukcja „select *” jest zła, jest tworzenie widoku. Jeśli utworzysz widok za pomocą opcji „select *”, a później dodasz kolumny do tabeli, definicja widoku i zwrócone dane nie będą pasować i będziesz musiał ponownie skompilować widoki, aby ponownie działały.
Wiem, że pisanie „select *” jest kuszące, ponieważ naprawdę nie lubię ręcznie określać wszystkich pól w moich zapytaniach, ale kiedy twój system zacznie się rozwijać, zobaczysz, że warto poświęcić ten dodatkowy czas / wysiłku w określaniu pól, zamiast poświęcać więcej czasu i wysiłku na usuwanie błędów w widokach lub optymalizację aplikacji.
źródło
Chociaż jawne wyświetlanie kolumn jest dobre dla wydajności, nie daj się zwariować.
Więc jeśli używasz wszystkich danych, spróbuj SELECT * dla uproszczenia (wyobraź sobie, że masz wiele kolumn i wykonanie zapytania JOIN ... może być okropne). Następnie - zmierz. Porównaj z zapytaniem z jawnie wymienionymi nazwami kolumn.
Nie spekuluj na temat wydajności, zmierz ją!
Jawne listowanie pomaga najbardziej, gdy masz jakąś kolumnę zawierającą duże dane (jak treść postu lub artykułu) i nie potrzebujesz jej w danym zapytaniu. Wtedy nie zwracając go na serwerze bazy danych odpowiedzi, można zaoszczędzić czas, przepustowość i przepustowość dysku. Wynik zapytania będzie również mniejszy, co jest dobre dla każdej pamięci podręcznej zapytań.
źródło
Naprawdę powinieneś wybierać tylko te pola, których potrzebujesz, i tylko wymaganą liczbę, tj
Poza bazą danych dynamiczne zapytania niosą ze sobą ryzyko ataków iniekcyjnych i zniekształconych danych. Zwykle można to obejść za pomocą procedur składowanych lub zapytań parametrycznych. Ponadto (chociaż nie jest to duży problem) serwer musi generować plan wykonania za każdym razem, gdy wykonywane jest dynamiczne zapytanie.
źródło
Zaznaczanie jest równie wydajne (pod względem szybkości), jeśli używasz * lub kolumn.
Różnica dotyczy pamięci, a nie szybkości. Po wybraniu kilku kolumn SQL Server musi przydzielić miejsce w pamięci, aby obsłużyć zapytanie, w tym wszystkie dane dla wszystkich żądanych kolumn, nawet jeśli używasz tylko jednej z nich.
Z punktu widzenia wydajności liczy się plan wykonania, który z kolei zależy w dużej mierze od Twojej klauzuli WHERE i liczby JOIN, OUTER JOIN itp.
W przypadku twojego pytania użyj SELECT *. Jeśli potrzebujesz wszystkich kolumn, nie ma różnicy w wydajności.
źródło
NIE jest szybsze użycie jawnych nazw pól w porównaniu z *, wtedy i tylko wtedy, gdy potrzebujesz danych dla wszystkich pól.
Oprogramowanie klienta nie powinno zależeć od kolejności zwracanych pól, więc to też bzdura.
I jest możliwe (choć mało prawdopodobne), że musisz pobrać wszystkie pola za pomocą *, ponieważ nie wiesz jeszcze, jakie pola istnieją (pomyśl o bardzo dynamicznej strukturze bazy danych).
Inną wadą używania jawnych nazw pól jest to, że jeśli jest ich wiele i są długie, to utrudnia to odczytanie kodu i / lub dziennika zapytań.
Dlatego zasada powinna brzmieć: jeśli potrzebujesz wszystkich pól, użyj *, jeśli potrzebujesz tylko podzbioru, nazwij je jawnie.
źródło
Wynik jest zbyt duży. Generowanie i wysyłanie wyniku z silnika SQL do klienta jest powolne.
Strona klienta, będąc ogólnym środowiskiem programistycznym, nie jest i nie powinna być zaprojektowana do filtrowania i przetwarzania wyników (np. Klauzula WHERE, klauzula ORDER), ponieważ liczba wierszy może być ogromna (np. Dziesiątki milionów wierszy).
źródło
Nazwanie każdej kolumny, którą spodziewasz się uzyskać w aplikacji, zapewnia również, że aplikacja nie zepsuje się, jeśli ktoś zmieni tabelę, o ile kolumny są nadal obecne (w dowolnej kolejności).
źródło
To zależy od wersji twojego serwera DB, ale nowoczesne wersje SQL mogą buforować plan w obie strony. Powiedziałbym, że wybierz wszystko, co jest najbardziej możliwe do utrzymania dzięki kodowi dostępu do danych.
źródło
Jednym z powodów, dla których lepiej jest dokładnie określić, które kolumny mają być, są możliwe przyszłe zmiany w strukturze tabeli.
Jeśli wczytujesz dane ręcznie, używając podejścia opartego na indeksach, aby wypełnić strukturę danych wynikami zapytania, to w przyszłości po dodaniu / usunięciu kolumny będziesz mieć bóle głowy, próbując dowiedzieć się, co poszło nie tak.
Jeśli chodzi o to, co jest szybsze, zwrócę się do innych za ich wiedzę.
źródło
Jak w przypadku większości problemów, zależy to od tego, co chcesz osiągnąć. Jeśli chcesz utworzyć siatkę bazy danych, która będzie zezwalać na wszystkie kolumny w dowolnej tabeli, odpowiedzią jest „Wybierz *”. Jeśli jednak będziesz potrzebować tylko niektórych kolumn, a dodawanie lub usuwanie kolumn z zapytania odbywa się rzadko, określ je indywidualnie.
Zależy to również od ilości danych, które chcesz przesłać z serwera. Jeśli jedna z kolumn jest zdefiniowana jako notatka, grafika, blob itp. I nie potrzebujesz tej kolumny, lepiej nie używaj opcji „Wybierz *”, bo otrzymasz całą masę danych, których nie potrzebujesz chcesz, a Twoja wydajność może ucierpieć.
źródło
Aby dodać do tego, co powiedzieli wszyscy inni, jeśli wszystkie wybrane przez Ciebie kolumny są uwzględnione w indeksie, zestaw wyników zostanie pobrany z indeksu zamiast wyszukiwać dodatkowe dane z SQL.
źródło
SELECT * jest konieczne, jeśli chce się uzyskać metadane, takie jak liczba kolumn.
źródło
Co powiedzieli wszyscy powyżej, a ponadto:
Jeśli dążysz do czytelnego, możliwego do utrzymania kodu, zrób coś takiego:
SELECT foo, bar FROM widżety;
jest natychmiast czytelny i pokazuje zamiar. Jeśli zadzwonisz, wiesz, co otrzymujesz. Jeśli widżety mają tylko kolumny foo i bar, to wybranie * oznacza, że nadal musisz pomyśleć o tym, co otrzymujesz, potwierdzić, że kolejność jest poprawnie zmapowana itp. Jeśli jednak widżety mają więcej kolumn, ale interesuje Cię tylko foo i bar, kod staje się nieczytelny, gdy pytasz o symbol wieloznaczny, a następnie używasz tylko części zwróconych.
źródło
Pamiętaj, że jeśli z definicji masz sprzężenie wewnętrzne, nie potrzebujesz wszystkich kolumn, ponieważ dane w kolumnach sprzężenia są powtarzane.
To nie jest tak, że wyświetlanie kolumn na serwerze SQl jest trudne lub nawet czasochłonne. Po prostu przeciągasz je z przeglądarki obiektów (możesz pobrać wszystko za jednym razem, przeciągając z kolumn słów). Aby na stałe obniżyć wydajność systemu (ponieważ może to zmniejszyć użycie indeksów i dlatego, że wysyłanie niepotrzebnych danych przez sieć jest kosztowne) i zwiększyć prawdopodobieństwo, że wystąpią nieoczekiwane problemy podczas zmiany bazy danych (czasami dodawane są kolumny, które na przykład nie chcesz, aby użytkownik widział), aby zaoszczędzić mniej niż minutę czasu programowania, jest krótkowzroczne i nieprofesjonalne.
źródło
Jeśli chodzi o wydajność, zauważyłem komentarze, że oba są równe. ale aspekt użyteczności jest kilka plusów i -ów
Kiedy używasz (wybierz *) w zapytaniu i jeśli ktoś zmieni tabelę i doda nowe pola, które nie są potrzebne w poprzednim zapytaniu, jest to niepotrzebny narzut. A co jeśli nowo dodane pole to blob lub pole obrazu ??? wtedy czas odpowiedzi na zapytanie będzie bardzo długi.
Z drugiej strony, jeśli używasz (wybierz kolumnę1, kolumnę2, ..) i jeśli tabela zostanie zmieniona i dodana nowe pola i jeśli te pola są potrzebne w zestawie wyników, zawsze musisz edytować zapytanie wybierające po zmianie tabeli.
Ale radzę zawsze używać select col1, col2, ... w zapytaniach i zmieniać zapytanie, jeśli tabela zostanie zmieniona później ...
źródło
Absolutnie zdefiniuj kolumny, które chcesz zaznaczyć za każdym razem. Nie ma powodu, aby tego nie robić, a poprawa wydajności jest tego warta.
Nigdy nie powinni dawać opcji „WYBIERZ *”
źródło
Jeśli potrzebujesz każdej kolumny, po prostu użyj SELECT *, ale pamiętaj, że kolejność może się zmienić, więc gdy korzystasz z wyników, uzyskaj do nich dostęp według nazwy, a nie indeksu.
Zignorowałbym komentarze na temat tego, jak * musi przejść, aby uzyskać listę - istnieje prawdopodobieństwo, że analizowane są i sprawdzanie poprawności nazwanych kolumn jest równe czasowi przetwarzania, jeśli nie więcej. Nie optymalizuj przedwcześnie ;-)
źródło
Jeśli chodzi o efektywność wykonania, nie widzę żadnej znaczącej różnicy. Ale dla wydajności programistów zapisałbym nazwy pól ponieważ
źródło
hej, bądź praktyczny. użyj select * podczas tworzenia prototypów i wybierz określone kolumny podczas wdrażania i wdrażania. z punktu widzenia planu wykonania oba są stosunkowo identyczne w nowoczesnych systemach. jednak wybranie określonych kolumn ogranicza ilość danych, które muszą zostać pobrane z dysku, zapisane w pamięci i przesłane przez sieć.
ostatecznie najlepszym planem jest wybranie określonych kolumn.
źródło