netcoffee.pl*po godzinach - reaktywacja

Ten blog jest kontynuacją bloga dostępnego ongiś pod adresem netcoffee.pl/pogodzinach.
Artykuły, które na to zasługują są przenoszone do nowej wersji bloga. Pozostałe wkrótce znikną.

2006-01-15

Optymalizacja bazy MySql - część II

Wcześniej (Prędkość czy miejsce) pisałem, jak można zaprojektować tabelę MySQL aby baza działała szybciej lub zajmowała mniej miejsca. Teraz przedstawiam garść innych porad:

używaj pól o jak najmiejszym rozmiarze
zmniejszenie rekordu redukuje ilość operacji dyskowych. Jeżeli przechowujesz hasło w postaci hasza md5, użyj pola char(32) a nie varchar(100)
deklaruj kolumny jako NOT NULL
zmniejszysz rozmiar rekordu
dla tabel MyISAM używaj rekordu o stałej długości
patrz: Prędkość czy miejsce
podstawowy indeks tabeli powinien być tak mały, jak to możliwe
przyspieszy to przeszukiwanie i tworzenie pliku indeksu
twórz indeksy których naprawdę potrzebujesz
tworzenie i odczytywanie indeksu też zajmuje czas. Indeksuj te kolumny, których używasz w części WHERE, ORDER BY lub GROUP BY zapytania. Nie musisz indeksować kolumn, których używasz tylko w części SELECT
pierwsza kolumna złożonego klucza powinna być kolumną najczęściej używaną
przyspieszy to przeszukiwanie indeksu
jeżeli pobierasz wiele kolumn z tabeli, najpierw użyj kolumny posiadającej wiele duplikatów
jeżeli kolumna ma unikalny prefiks na kilku pierwszych znakach, lepiej jest zindeksować tylko te kilka pierwszych znaków
użyj do tego funkcji MySQL pozwalającej na tworzeniu indeksu lewej części kolumny znakowej
w pewnych warunkach może przydać się podzielenie tabeli na dwie
w ten sposób możesz uzyskać w jednej tabeli rekordy o stałej długości
indeksy działają wydajniej dla kolumn, które mają dużą ilość unikalnych wartości w stosunku do ilości rekordów (ang. cardinality)
lepiej działa indeks dla kolumny 'login' (wszystkie wartości unikalne) niż dla kolumny 'wojewodztwo' (tylko 16 różnych wartości)
zwróć uwagę na typ pól podczas porównywania
jeżeli wyszukujesz rekordy na podstawie pola typu INTEGER, nie używaj porównania tego pola z typem STRING (np. WHERE id = '78'). Lepiej porównuj pola tego samego typu (np. WHERE id = 78). Jeżeli porównujesz wartość pola z wartością innego pola, zadbaj aby miały one ten sam typ. Dzięki temu unikniesz konieczności rzutowania. Pamiętaj także, że int i bigint to inne typy pól oraz char(10) nie odpowiada polu char(12).
staraj się umieszczać indeksowane samotnie po jednej stronie porównania
w przeciwnym wypadku MySQL nie będzie mógł użyć indeksów. Lepszą wydajność uzyskasz pisząc 'WHERE i < 4 / 2' niż 'WHERE i *2 < 2'
nie używaj znaków wieloznacznych na początku porówanania LIKE
używaj pól typu ENUM jeżeli to możliwe

2 comments:

  1. Co do pierwszego punktu - mógłbyś trochę rozwinąć tą myśl dlaczego VARCHAR(100) jest lepsze od CHAR(32)? Przecież pole typu VARCHAR działa tak, że alokuje dokładnie tyle miejsca ile potrzebuje, zamiast stałego rozmiaru w przypadku CHAR'ów, a przynajmniej taką wiedzę wyniosłem z zajęć na studiach, z bólem przyznaję, że nie weryfikowałem tego. Z góry dzięki za odpowiedź.

    ReplyDelete
  2. @Tomasz Kowalczyk
    Nie napisałem, że varchar(100) jest lepszy - wręcz odwrotnie :)

    Generalnie powinieneś zdecydować się na jeden z typów rekordów - o stałej lub zmiennej długości - więcej przeczytasz o tym tutaj: http://pogodzinach.netcoffee.pl/2005/10/predkosc-czy-miejsce.html - ja założyłem, że lepszy jest model w którym rekord ma stałą długość.
    W pierwszym punkcie czytelniej byłoby gdybym porównał pola char(100) i char(32) - tu przewaga char(32) jest widoczna gołym okiem.

    Ale nawet, jeżeli weźmiemy pod uwagę dwa typy - varchar(100) i varchar(32) to - teoretycznie przynajmniej - są w naszym przypadku równoważne. Jednak podana dokładna wielkość (32) może być dobrą wskazówką przy późniejszej analizie kodu i struktury bazy danych. Szczególnie, gdy brak dokumentacji :)

    ReplyDelete