Jakie są typowe błędy w tworzeniu baz danych popełniane przez twórców aplikacji?
Jakie są typowe błędy w tworzeniu baz danych popełniane przez twórców aplikacji?
Odpowiedzi:
1. Nieużywanie odpowiednich wskaźników
Jest to stosunkowo łatwe, ale wciąż zdarza się cały czas. Klucze obce powinny mieć indeksy. Jeśli używasz pola w WHERE
, powinieneś (prawdopodobnie) mieć na nim indeks. Takie indeksy często powinny obejmować wiele kolumn na podstawie zapytań, które należy wykonać.
2. Niewymaganie integralności referencyjnej
Twoja baza danych może się tutaj różnić, ale jeśli twoja baza danych obsługuje integralność referencyjną - co oznacza, że wszystkie klucze obce mają gwarancję wskazywania na istniejącą jednostkę - powinieneś jej używać.
Dość często obserwuje się ten błąd w bazach danych MySQL. Nie wierzę, że MyISAM obsługuje to. InnoDB działa. Znajdziesz osoby, które używają MyISAM lub te, które używają InnoDB, ale i tak go nie używają.
Więcej tutaj:
3. Używanie naturalnych, a nie zastępczych (technicznych) kluczy podstawowych
Klucze naturalne to klucze oparte na danych o znaczeniu zewnętrznym, które są (rzekomo) unikalne. Typowymi przykładami są kody produktów, dwuliterowe kody stanów (USA), numery ubezpieczenia społecznego i tak dalej. Klucze zastępcze lub techniczne podstawowe to te, które absolutnie nie mają żadnego znaczenia poza systemem. Są one wymyślone wyłącznie w celu identyfikacji bytu i zazwyczaj są to pola automatycznie inkrementujące (SQL Server, MySQL, inne) lub sekwencje (przede wszystkim Oracle).
Moim zdaniem zawsze powinieneś używać kluczy zastępczych. Ten problem pojawił się w następujących pytaniach:
Jest to nieco kontrowersyjny temat, w sprawie którego nie osiągniesz powszechnej zgody. Chociaż możesz znaleźć ludzi, którzy uważają, że klucze naturalne są w pewnych sytuacjach OK, nie spotkasz się z żadną krytyką kluczy zastępczych poza tym, że są prawdopodobnie niepotrzebne. To dość mały minus, jeśli mnie o to poprosisz.
Pamiętaj, że nawet kraje mogą przestać istnieć (na przykład Jugosławia).
4. Pisanie zapytań wymagających DISTINCT
pracy
Często widzisz to w zapytaniach generowanych przez ORM. Spójrz na dane wyjściowe dziennika z Hibernacji, a zobaczysz, że wszystkie zapytania zaczynają się od:
SELECT DISTINCT ...
Jest to skrót do upewnienia się, że nie zwracasz zduplikowanych wierszy, a tym samym nie otrzymujesz zduplikowanych obiektów. Czasami zobaczysz, że ludzie to robią. Jeśli zobaczysz to za dużo, to prawdziwa czerwona flaga. Nie DISTINCT
jest to złe lub nie ma prawidłowych aplikacji. Robi to (z obu powodów), ale nie jest to surogat ani przerwa w pisaniu poprawnych zapytań.
Od Dlaczego nienawidzę DISTINCT :
Moim zdaniem sytuacja zaczyna się psuć, gdy deweloper buduje solidne zapytanie, łączy tabele i nagle zdaje sobie sprawę, że wygląda na to, że robi zduplikowane (lub nawet więcej) wiersze i jego natychmiastowa odpowiedź ... jego „rozwiązaniem” tego „problemu” jest wrzucenie słowa kluczowego DISTINCT i POOF wszystkie jego problemy znikają.
5. Preferowanie agregacji nad złączeniami
Innym częstym błędem twórców aplikacji bazodanowych jest nie zdawanie sobie sprawy z tego, o ile droższe agregowanie (tj. GROUP BY
Klauzula) można porównać do złączeń.
Aby dać wyobrażenie o tym, jak bardzo jest to rozpowszechnione, pisałem na ten temat kilka razy tutaj i byłem za niego bardzo oceniany. Na przykład:
Z instrukcji SQL - „dołącz” vs „grupuj według i mając” :
Pierwsze zapytanie:
SELECT userid FROM userrole WHERE roleid IN (1, 2, 3) GROUP by userid HAVING COUNT(1) = 3
Czas zapytania: 0,312 s
Drugie zapytanie:
SELECT t1.userid FROM userrole t1 JOIN userrole t2 ON t1.userid = t2.userid AND t2.roleid = 2 JOIN userrole t3 ON t2.userid = t3.userid AND t3.roleid = 3 AND t1.roleid = 1
Czas zapytania: 0,016 s
Zgadza się. Proponowana wersja dołączenia jest dwadzieścia razy szybsza niż wersja zagregowana.
6. Nie upraszczanie skomplikowanych zapytań poprzez widoki
Nie wszyscy dostawcy baz danych obsługują widoki, ale dla tych, którzy to robią, mogą znacznie uprościć zapytania, jeśli są używane rozsądnie. Na przykład w jednym projekcie użyłem ogólnego modelu Party dla CRM. Jest to niezwykle wydajna i elastyczna technika modelowania, ale może prowadzić do wielu połączeń. W tym modelu były:
Przykład:
Jest więc pięć tabel połączonych, by połączyć Teda z jego pracodawcą. Zakładasz, że wszyscy pracownicy to Osoby (nie organizacje) i udostępniasz widok pomocnika:
CREATE VIEW vw_employee AS
SELECT p.title, p.given_names, p.surname, p.date_of_birth, p2.party_name employer_name
FROM person p
JOIN party py ON py.id = p.id
JOIN party_role child ON p.id = child.party_id
JOIN party_role_relationship prr ON child.id = prr.child_id AND prr.type = 'EMPLOYMENT'
JOIN party_role parent ON parent.id = prr.parent_id = parent.id
JOIN party p2 ON parent.party_id = p2.id
I nagle masz bardzo prosty widok danych, które chcesz, ale na bardzo elastycznym modelu danych.
7. Brak dezynfekcji danych wejściowych
To jest ogromne. Teraz lubię PHP, ale jeśli nie wiesz, co robisz, bardzo łatwo jest stworzyć witryny podatne na atak. Nic nie podsumowuje lepiej niż historia małych stołów Bobby'ego .
Dane przekazywane przez użytkownika za pomocą adresów URL, danych formularzy i plików cookie należy zawsze traktować jako wrogie i odkażone. Upewnij się, że otrzymujesz to, czego oczekujesz.
8. Nieużywanie przygotowanych wyciągów
Przygotowane instrukcje mają miejsce podczas kompilowania zapytania pomniejszonego o dane użyte we wstawkach, aktualizacjach i WHERE
klauzulach, a następnie dostarczone później. Na przykład:
SELECT * FROM users WHERE username = 'bob'
vs
SELECT * FROM users WHERE username = ?
lub
SELECT * FROM users WHERE username = :username
w zależności od platformy.
Widziałem bazy danych rzucane na kolana. Zasadniczo za każdym razem, gdy nowoczesna baza danych napotka nowe zapytanie, musi je skompilować. Jeśli napotka zapytanie, które było wcześniej widoczne, dajesz bazie danych możliwość buforowania skompilowanego zapytania i planu wykonania. Często wykonując zapytanie, dajesz bazę danych szansę, aby to ustalić i odpowiednio zoptymalizować (na przykład, przypinając skompilowane zapytanie w pamięci).
Korzystanie z przygotowanych instrukcji daje także znaczące statystyki dotyczące częstotliwości korzystania z niektórych zapytań.
Przygotowane wyciągi lepiej ochronią Cię przed atakami iniekcyjnymi SQL.
9. Niewystarczająco normalizujący
Normalizacja bazy danych jest zasadniczo procesem optymalizacji projektu bazy danych lub tego, jak organizujesz dane w tabele.
Właśnie w tym tygodniu natknąłem się na kod, w którym ktoś zaimplementował tablicę i wstawił ją do jednego pola w bazie danych. Normalizacja polegałaby na traktowaniu elementu tej tablicy jako osobnego wiersza w tabeli potomnej (tj. Relacji jeden do wielu).
Pojawiło się to również w Najlepszej metodzie przechowywania listy identyfikatorów użytkowników :
Widziałem w innych systemach, że lista jest przechowywana w szeregowej tablicy PHP.
Ale brak normalizacji występuje w wielu formach.
Więcej:
10. Zbyt duża normalizacja
Może się to wydawać sprzecznością z poprzednim punktem, ale normalizacja, podobnie jak wiele innych rzeczy, jest narzędziem. Jest środkiem do celu, a nie celem samym w sobie. Myślę, że wielu programistów zapomina o tym i zaczyna traktować „środki” jako „koniec”. Testowanie jednostkowe jest tego najlepszym przykładem.
Kiedyś pracowałem nad systemem, który miał ogromną hierarchię dla klientów, która działała w następujący sposób:
Licensee -> Dealer Group -> Company -> Practice -> ...
tak, że musiałeś połączyć około 11 tabel razem, zanim uzyskasz jakieś znaczące dane. To był dobry przykład zbyt daleko posuniętej normalizacji.
Co więcej, ostrożna i przemyślana denormalizacja może przynieść ogromne korzyści w zakresie wydajności, ale musisz być bardzo ostrożny.
Więcej:
11. Korzystanie z ekskluzywnych łuków
Łuk wyłączny jest częstym błędem, gdy tabela jest tworzona z dwoma lub więcej kluczami obcymi, przy czym jeden i tylko jeden z nich może mieć wartość inną niż null. Duży błąd. Z jednej strony utrzymanie integralności danych jest o wiele trudniejsze. W końcu, nawet przy integralności referencyjnej, nic nie stoi na przeszkodzie, aby ustawić dwa lub więcej z tych kluczy obcych (pomimo złożonych ograniczeń sprawdzania).
Od praktycznego przewodnika po projektach relacyjnych baz danych :
Zdecydowanie odradzamy tworzenie ekskluzywnych łuków wszędzie tam, gdzie to możliwe, z tego dobrego powodu, że mogą być kłopotliwi w pisaniu kodu i stwarzają więcej trudności konserwacyjnych.
12. W ogóle nie przeprowadzanie analizy wydajności zapytań
Pragmatyzm króluje przede wszystkim, szczególnie w świecie baz danych. Jeśli trzymasz się zasad do tego stopnia, że stały się dogmatem, prawdopodobnie popełniłeś błędy. Weź przykład agregowanych zapytań z góry. Wersja zagregowana może wyglądać „ładnie”, ale jej wydajność jest żałosna. Porównanie wyników powinno zakończyć debatę (ale tak się nie stało), ale bardziej do rzeczy: wypowiadanie tak źle poinformowanych poglądów jest przede wszystkim ignoranckie, a nawet niebezpieczne.
13. Nadmierne poleganie na UNION ALL, a zwłaszcza na konstrukcjach UNION
UNIA w języku SQL łączy jedynie przystające zestawy danych, co oznacza, że mają ten sam typ i liczbę kolumn. Różnica między nimi polega na tym, że UNION ALL jest prostą konkatenacją i powinien być preferowany, gdy tylko jest to możliwe, podczas gdy UNION pośrednio dokona DISTINCT, aby usunąć duplikaty krotek.
Związki, jak DISTINCT, mają swoje miejsce. Istnieją prawidłowe aplikacje. Ale jeśli robisz ich dużo, szczególnie w podkwerendach, prawdopodobnie robisz coś złego. Może to być przypadek złej konstrukcji zapytania lub źle zaprojektowanego modelu danych zmuszającego do robienia takich rzeczy.
UNIA, szczególnie gdy są używane w sprzężeniach lub zależnych podkwerendach, mogą uszkodzić bazę danych. Staraj się ich unikać, gdy tylko jest to możliwe.
14. Używanie warunków LUB w zapytaniach
To może wydawać się nieszkodliwe. W końcu AND są OK. LUB powinno być OK, prawda? Źle. Zasadniczo warunek AND ogranicza zestaw danych, podczas gdy warunek OR go powiększa , ale nie w sposób, który nadaje się do optymalizacji. Zwłaszcza gdy różne warunki OR mogą się przecinać, co zmusza optymalizator do skutecznego wykonania operacji WYRÓŻNIAJĄ wynik.
Zły:
... WHERE a = 2 OR a = 5 OR a = 11
Lepszy:
... WHERE a IN (2, 5, 11)
Teraz Twój optymalizator SQL może skutecznie zamienić pierwsze zapytanie w drugie. Ale może nie. Po prostu nie rób tego.
15. Nie projektuje swojego modelu danych, aby nadawał się do wysokowydajnych rozwiązań
To trudny punkt do oszacowania. Zazwyczaj obserwuje się to przez jego działanie. Jeśli piszesz dziwne zapytania do stosunkowo prostych zadań lub że zapytania o znalezienie stosunkowo prostych informacji nie są wydajne, prawdopodobnie masz słaby model danych.
W pewnym sensie ten punkt podsumowuje wszystkie wcześniejsze, ale jest to raczej przestroga, że robienie rzeczy takich jak optymalizacja zapytań jest często wykonywane jako pierwsze, a drugie. Przed optymalizacją wydajności powinieneś upewnić się, że masz dobry model danych. Jak powiedział Knuth:
Przedwczesna optymalizacja jest źródłem wszelkiego zła
16. Nieprawidłowe użycie transakcji bazy danych
Wszystkie zmiany danych dla określonego procesu powinny mieć charakter atomowy. To znaczy, jeśli operacja się powiedzie, zrobi to w pełni. Jeśli zawiedzie, dane pozostaną niezmienione. - Nie powinno być możliwości wprowadzenia zmian w połowie dokonanych.
Idealnie najprostszym sposobem na osiągnięcie tego jest to, że cały projekt systemu powinien dążyć do obsługi wszystkich zmian danych za pomocą pojedynczych instrukcji INSERT / UPDATE / DELETE. W takim przypadku nie jest wymagana specjalna obsługa transakcji, ponieważ aparat bazy danych powinien to zrobić automatycznie.
Jeśli jednak jakiekolwiek procesy wymagają wykonania wielu instrukcji jako jednostki w celu utrzymania danych w spójnym stanie, konieczna jest odpowiednia kontrola transakcji.
Zalecane jest również zwrócenie szczególnej uwagi na subtelności tego, w jaki sposób warstwa łączności bazy danych i silnik bazy danych oddziałują w tym zakresie.
17. Niezrozumienie paradygmatu opartego na zbiorze
Język SQL jest zgodny ze specyficznym paradygmatem dostosowanym do określonych rodzajów problemów. Niezależnie od różnych rozszerzeń specyficznych dla dostawcy, język stara się radzić sobie z problemami, które są trywialne w językach takich jak Java, C #, Delphi itp.
Ten brak zrozumienia objawia się na kilka sposobów.
Określ wyraźny podział odpowiedzialności i staraj się używać odpowiedniego narzędzia do rozwiązania każdego problemu.
Kluczowe błędy w projektowaniu i programowaniu baz danych popełniane przez programistów
Samolubny projekt i użycie bazy danych. Programiści często traktują bazę danych jako osobistą składnicę obiektów trwałych bez uwzględnienia potrzeb innych zainteresowanych stron w danych. Dotyczy to również architektów aplikacji. Zły projekt bazy danych i integralność danych utrudniają osobom trzecim pracę z danymi i mogą znacznie zwiększyć koszty cyklu życia systemu. Raportowanie i MIS bywają kiepskim kuzynem w projektowaniu aplikacji i są robione tylko po namyśle.
Nadużywanie zdenormalizowanych danych. Przesadzanie zdormalizowanych danych i próby utrzymania ich w aplikacji to przepis na problemy z integralnością danych. Oszczędnie używaj denormalizacji. Brak chęci dodania złączenia do zapytania nie jest usprawiedliwieniem denormalizacji.
Boisz się pisać SQL. SQL nie jest nauką rakietową i jest całkiem dobry w wykonywaniu swojej pracy. Warstwy mapowania O / R są dość dobre w wykonywaniu 95% zapytań, które są proste i dobrze pasują do tego modelu. Czasami SQL jest najlepszym sposobem na wykonanie zadania.
Dogmatyczne zasady „bez przechowywanych procedur”. Niezależnie od tego, czy uważasz, że procedury przechowywane są złe, tego rodzaju dogmatyczne podejście nie ma miejsca w projekcie oprogramowania.
Niezrozumienie projektu bazy danych. Normalizacja jest twoim przyjacielem i nie jest nauką o rakietach. Łączenie i liczność są dość prostymi pojęciami - jeśli jesteś zaangażowany w tworzenie aplikacji bazodanowych, naprawdę nie ma wymówki, aby ich nie zrozumieć.
Nadużywanie i / lub zależność od procedur przechowywanych.
Niektórzy twórcy aplikacji postrzegają procedury składowane jako bezpośrednie rozszerzenie kodu warstwy środkowej / interfejsu użytkownika. Wydaje się, że jest to wspólna cecha programistów stosów Microsoft (jestem jedną z nich, ale wyrosłem z niej) i tworzy wiele procedur składowanych, które wykonują złożoną logikę biznesową i przetwarzanie przepływu pracy. Znacznie lepiej jest to zrobić gdzie indziej.
Procedury przechowywane są przydatne, gdy faktycznie udowodniono, że jakiś rzeczywisty czynnik techniczny wymaga ich użycia (na przykład wydajność i bezpieczeństwo) Na przykład utrzymanie agregacji / filtrowania dużych zestawów danych „blisko danych”.
Niedawno musiałem pomóc w utrzymaniu i ulepszeniu dużej aplikacji komputerowej Delphi, której 70% logiki biznesowej i reguł wdrożono w 1400 procedurach przechowywanych SQL Server (reszta w procedurach obsługi zdarzeń interfejsu użytkownika). Był to koszmar, głównie z powodu trudności z wprowadzeniem skutecznego testowania jednostkowego do TSQL, braku enkapsulacji i słabych narzędzi (debuggery, edytory).
Współpracując z zespołem Java w przeszłości szybko przekonałem się, że w tym środowisku często jest coś zupełnie przeciwnego. Pewien architekt Java powiedział mi kiedyś: „Baza danych służy do danych, a nie do kodu”.
W dzisiejszych czasach uważam, że błędem jest nieuwzględnianie przechowywanych procesów w ogóle, ale należy ich używać oszczędnie (nie domyślnie) w sytuacjach, w których zapewniają one użyteczne korzyści (zobacz inne odpowiedzi).
Problem numer jeden? Testują tylko na bazach zabawek. Więc nie mają pojęcia, że ich SQL będzie się czołgał, gdy baza danych się powiększy, a ktoś musi przyjść i naprawić to później (ten dźwięk, który słyszysz, to zgrzytanie moimi zębami).
Nie używa indeksów.
Niska wydajność spowodowana skorelowanymi podzapytaniami
Przez większość czasu chcesz unikać skorelowanych podkwerend. Podkwerenda jest skorelowana, jeśli w podkwerendie znajduje się odwołanie do kolumny z zewnętrznego zapytania. Gdy tak się dzieje, podzapytanie jest wykonywane co najmniej raz dla każdego zwracanego wiersza i może być wykonywane więcej razy, jeśli zostaną zastosowane inne warunki po zastosowaniu warunku zawierającego skorelowane podzapytanie.
Wybacz wymyślony przykład i składnię Oracle, ale powiedzmy, że chciałeś znaleźć wszystkich pracowników, którzy zostali zatrudnieni w którymkolwiek z twoich sklepów od ostatniego razu, gdy sklep dokonał sprzedaży mniejszej niż 10 000 USD dziennie.
select e.first_name, e.last_name
from employee e
where e.start_date >
(select max(ds.transaction_date)
from daily_sales ds
where ds.store_id = e.store_id and
ds.total < 10000)
Podkwerenda w tym przykładzie jest skorelowana z zewnętrznym zapytaniem store_id i zostanie wykonana dla każdego pracownika w twoim systemie. Jednym ze sposobów optymalizacji tego zapytania jest przeniesienie podzapytania do widoku wbudowanego.
select e.first_name, e.last_name
from employee e,
(select ds.store_id,
max(s.transaction_date) transaction_date
from daily_sales ds
where ds.total < 10000
group by s.store_id) dsx
where e.store_id = dsx.store_id and
e.start_date > dsx.transaction_date
W tym przykładzie zapytanie w klauzuli from jest teraz widokiem wbudowanym (ponownie niektóre składnie specyficzne dla Oracle) i jest wykonywane tylko raz. W zależności od modelu danych to zapytanie prawdopodobnie zostanie wykonane znacznie szybciej. Będzie działać lepiej niż pierwsze zapytanie wraz ze wzrostem liczby pracowników. Pierwsze zapytanie mogłoby faktycznie działać lepiej, gdyby było niewielu pracowników i wiele sklepów (a być może wiele sklepów nie miało pracowników), a tabela Daily_sales byłaby indeksowana na store_id. To nie jest prawdopodobny scenariusz, ale pokazuje, w jaki sposób skorelowane zapytanie może być skuteczniejsze niż alternatywa.
Wiele razy widziałem, jak młodsi programiści korelowali podkwerendy i zwykle miało to poważny wpływ na wydajność. Jednak usuwając skorelowane podzapytanie, należy zapoznać się z planem wyjaśniania przed i po, aby upewnić się, że nie pogarsza się wydajność.
Używanie programu Access zamiast „prawdziwej” bazy danych. Istnieje wiele wspaniałych małych, a nawet bezpłatnych baz danych, takich jak SQL Express , MySQL i SQLite, które będą działać i skalować znacznie lepiej. Aplikacje często wymagają skalowania w nieoczekiwany sposób.
Korzystanie z Excela do przechowywania (dużych ilości) danych.
Widziałem firmy posiadające tysiące wierszy i korzystające z wielu arkuszy (z powodu limitu wierszy 65535 w poprzednich wersjach programu Excel).
Excel doskonale nadaje się do raportów, prezentacji danych i innych zadań, ale nie powinien być traktowany jako baza danych.
Chciałbym dodać: Preferowanie „eleganckiego” kodu nad kodem o wysokiej wydajności. Kod najlepiej działający w bazach danych jest często brzydki dla oka twórcy aplikacji.
Wiara w ten nonsens o przedwczesnej optymalizacji. Bazy danych muszą uwzględniać wydajność w pierwotnym projekcie i przy każdym późniejszym rozwoju. Wydajność stanowi 50% projektu bazy danych (40% to integralność danych, a ostatnie 10% to bezpieczeństwo). Bazy danych, które nie są budowane od podstaw w celu działania, będą działać źle po umieszczeniu rzeczywistych użytkowników i rzeczywistego ruchu w bazie danych. Przedwczesna optymalizacja nie oznacza braku optymalizacji! Nie oznacza to, że powinieneś pisać kod, który prawie zawsze będzie działał źle, ponieważ jest ci łatwiej (kursory na przykład, które nigdy nie powinny być dozwolone w produkcyjnej bazie danych, chyba że wszystko inne zawiedzie). Oznacza to, że nie musisz patrzeć na wyciskanie ostatniego kawałka wydajności, dopóki nie musisz. Wiele wiadomo na temat tego, co będzie działać lepiej w bazach danych,
Nieużywane sparametryzowane zapytania. Są bardzo przydatne w powstrzymywaniu wstrzykiwania SQL .
Jest to konkretny przykład braku dezynfekcji danych wejściowych, wspomniany w innej odpowiedzi.
Nienawidzę tego, gdy programiści używają zagnieżdżonych instrukcji select lub nawet funkcji zwracają wynik instrukcji select w części „SELECT” zapytania.
Jestem właściwie zaskoczony, że nie widzę tego nigdzie indziej, być może przeoczyłem to, chociaż @adam ma wskazany podobny problem.
Przykład:
SELECT
(SELECT TOP 1 SomeValue FROM SomeTable WHERE SomeDate = c.Date ORDER BY SomeValue desc) As FirstVal
,(SELECT OtherValue FROM SomeOtherTable WHERE SomeOtherCriteria = c.Criteria) As SecondVal
FROM
MyTable c
W tym scenariuszu, jeśli MyTable zwraca 10000 wierszy, wynik jest taki, jakby zapytanie uruchomiło tylko zapytania 20001, ponieważ musiało uruchomić zapytanie początkowe plus zapytanie do każdej z pozostałych tabel raz dla każdej linii wyniku.
Programiści mogą uniknąć tej pracy w środowisku programistycznym, w którym zwracają tylko kilka wierszy danych, a tabele podrzędne zwykle zawierają tylko niewielką ilość danych, ale w środowisku produkcyjnym tego rodzaju zapytania mogą być wykładniczo kosztowne, ponieważ więcej dane są dodawane do tabel.
Lepszym (niekoniecznie idealnym) przykładem byłoby coś takiego:
SELECT
s.SomeValue As FirstVal
,o.OtherValue As SecondVal
FROM
MyTable c
LEFT JOIN (
SELECT SomeDate, MAX(SomeValue) as SomeValue
FROM SomeTable
GROUP BY SomeDate
) s ON c.Date = s.SomeDate
LEFT JOIN SomeOtherTable o ON c.Criteria = o.SomeOtherCriteria
Pozwala to optymalizatorom bazy danych na pomieszanie danych, a nie na żądanie dla każdego rekordu z głównej tabeli, i zwykle znajduję, kiedy muszę naprawić kod w miejscu, w którym ten problem został utworzony, zwykle w końcu zwiększam szybkość zapytań o 100% lub więcej, jednocześnie zmniejszając zużycie procesora i pamięci.
W przypadku baz danych opartych na SQL:
Nie robienie kopii zapasowej przed naprawieniem problemu w produkcyjnej bazie danych.
Używanie poleceń DDL dla przechowywanych obiektów (takich jak tabele, widoki) w procedurach przechowywanych.
Strach przed użyciem przechowywanego proc lub strach przed użyciem zapytań ORM wszędzie tam, gdzie jest to bardziej wydajne / odpowiednie w użyciu.
Ignorowanie użycia profilera bazy danych, który może dokładnie powiedzieć, na co ostatecznie konwertowane jest zapytanie ORM, a tym samym zweryfikować logikę, a nawet debugowanie, gdy nie używa się ORM.
Niewłaściwy poziom normalizacji . Chcesz się upewnić, że dane nie są duplikowane i że dzielisz dane na różne w razie potrzeby. Musisz również upewnić się, że nie przestrzegasz zbytnio normalizacji, ponieważ wpłynie to negatywnie na wydajność.
Traktowanie bazy danych jako mechanizmu przechowywania (tj. Gloryfikowanej biblioteki kolekcji), a tym samym podporządkowanie jej aplikacji (ignorowanie innych aplikacji, które współużytkują dane)
1 - Niepotrzebne użycie funkcji dla wartości w klauzuli where z wynikiem nieużywania tego indeksu.
Przykład:
where to_char(someDate,'YYYYMMDD') between :fromDate and :toDate
zamiast
where someDate >= to_date(:fromDate,'YYYYMMDD') and someDate < to_date(:toDate,'YYYYMMDD')+1
I w mniejszym stopniu: brak dodawania indeksów funkcjonalnych do tych wartości, które ich potrzebują ...
2 - Brak dodawania ograniczeń kontrolnych w celu zapewnienia ważności danych. Ograniczenia mogą być stosowane przez optymalizator zapytań, i NAPRAWDĘ pomagają upewnić się, że możesz ufać niezmiennikom. Po prostu nie ma powodu, aby ich nie używać.
3 - Dodawanie do tabel nietypowych kolumn z czystego lenistwa lub presji czasu. Rzeczy zwykle nie są zaprojektowane w ten sposób, ale ewoluują w ten sposób. Rezultat końcowy bez wątpienia to mnóstwo pracy nad uporządkowaniem bałaganu, gdy ugryzie Cię utrata integralności danych w przyszłych ewolucjach.
Pomyśl o tym, przeprojektowanie tabeli bez danych jest bardzo tanie. Tabela z kilkoma milionami rekordów bez integralności ... nie tak tanio przeprojektować. Tak więc wykonanie poprawnego projektu podczas tworzenia kolumny lub tabeli jest amortyzowane w pikach.
4 - nie tyle sama baza danych, co irytująca. Nie dbając o jakość kodu SQL. Fakt, że SQL jest wyrażony w tekście, nie pozwala ukryć logiki w stosach algorytmów manipulacji ciągami. Zupełnie możliwe jest pisanie SQL w tekście w sposób, który jest w rzeczywistości czytelny dla innych programistów.
To zostało powiedziane wcześniej, ale: indeksy, indeksy, indeksy . Widziałem tak wiele przypadków słabo działających aplikacji internetowych dla przedsiębiorstw, które zostały naprawione po prostu wykonując małe profilowanie (aby zobaczyć, które tabele były często atakowane), a następnie dodając indeks do tych tabel. Nie wymaga to nawet dużo wiedzy na temat pisania SQL, a wypłata jest ogromna.
Unikaj powielania danych, takich jak plaga. Niektóre osoby opowiadają się za tym, że niewielkie powielanie nie zaszkodzi i poprawi wydajność. Hej, nie mówię, że musisz torturować swój schemat do Trzeciej Normalnej Formy, dopóki nie będzie tak abstrakcyjny, że nawet DBA nie będzie wiedział, co się dzieje. Po prostu zrozum, że za każdym razem, gdy powielasz zestaw nazw, kodów pocztowych lub kodów wysyłkowych, kopie ostatecznie nie będą ze sobą zsynchronizowane. To się stanie. A potem będziesz się kopał podczas uruchamiania cotygodniowego skryptu konserwacji.
Na koniec: zastosuj jasną, spójną, intuicyjną konwencję nazewnictwa. W ten sam sposób, w jaki dobrze napisany fragment kodu powinien być czytelny, dobry schemat SQL lub zapytanie powinny być czytelne i praktycznie powiedzieć ci, co robi, nawet bez komentarzy. Podziękujesz sobie za sześć miesięcy, kiedy będziesz musiał utrzymywać stoły. "SELECT account_number, billing_date FROM national_accounts"
jest nieskończenie łatwiejszy w obsłudze niż „WYBIERZ ACCNTNBR, BILLDAT FROM NTNLACCTS”.
Najczęstszy błąd, jaki widziałem od dwudziestu lat: brak planowania. Wielu programistów utworzy bazę danych i tabele, a następnie będzie stale modyfikować i rozszerzać tabele podczas tworzenia aplikacji. Efektem końcowym jest często bałagan, nieefektywny i trudny do wyczyszczenia lub uproszczenia później.
a)
Twarde kodowanie wartości zapytań w łańcuchu b) Umieszczenie kodu zapytania bazy danych w akcji „OnButtonPress” w aplikacji Windows Forms
Widziałem oba.
Nie zwracanie wystarczającej uwagi na zarządzanie połączeniami bazy danych w aplikacji. Następnie dowiadujesz się, że aplikacja, komputer, serwer i sieć są zatkane.
Myśląc, że są DBA i projektantami danych / projektantami, gdy nie mają formalnej indoktrynacji w tych obszarach.
Myśląc, że ich projekt nie wymaga DBA, ponieważ wszystko jest łatwe / trywialne.
Niewłaściwe rozróżnienie między pracą, która powinna zostać wykonana w bazie danych, a pracą, która powinna zostać wykonana w aplikacji.
Nie sprawdzam poprawności kopii zapasowych lub nie tworzysz kopii zapasowej.
Osadzanie surowego SQL w kodzie.
Oto link do filmu pt. „ Klasyczne błędy w tworzeniu baz danych i pięć sposobów na ich przezwyciężenie ” autorstwa Scotta Walza
Niezrozumienie modelu współbieżności baz danych i jego wpływu na rozwój. Po fakcie łatwo jest dodawać indeksy i dostosowywać zapytania. Jednak aplikacje zaprojektowane bez odpowiedniego uwzględnienia punktów aktywnych, rywalizacji o zasoby i poprawnego działania (zakładając, że to, co właśnie przeczytałeś, jest nadal ważne!) Mogą wymagać znacznych zmian w bazie danych i warstwie aplikacji, aby je poprawić później.
Nie rozumiem, jak DBMS działa pod maską.
Nie można prawidłowo prowadzić drążka bez zrozumienia, jak działa sprzęgło. Nie możesz zrozumieć, jak korzystać z bazy danych, nie rozumiejąc, że tak naprawdę piszesz tylko do pliku na dysku twardym.
Konkretnie:
Czy wiesz, czym jest Indeks klastrowany? Czy pomyślałeś o tym, projektując swój schemat?
Czy wiesz, jak prawidłowo używać indeksów? Jak ponownie wykorzystać indeks? Czy wiesz, co to jest indeks ubezpieczenia?
Tak świetnie, masz indeksy. Jak duży jest 1 wiersz w twoim indeksie? Jak duży będzie indeks, gdy masz dużo danych? Czy to z łatwością zmieści się w pamięci? Jeśli nie, jest bezużyteczny jako indeks.
Czy kiedykolwiek używałeś EXPLAIN w MySQL? Świetny. Teraz bądź ze sobą szczery: Czy zrozumiałeś nawet połowę tego, co widziałeś? Nie, prawdopodobnie nie. Napraw to.
Czy rozumiesz pamięć podręczną zapytań? Czy wiesz, co sprawia, że zapytanie jest nie do buforowania?
Czy korzystasz z MyISAM? Jeśli POTRZEBUJESZ wyszukiwania pełnotekstowego, MyISAM jest badziewne. Użyj Sfinksa. Następnie przejdź do Inno.