Przeszukajmy polski fragment sieci na występowanie słów kluczowych: mysql „order by rand”. Co widzimy? Na pierwszym miejscu mamy link wyjaśniający, jak najprościej pobrać losowe rekordy z tabeli. Spora część innych linków także opisuje stosowanie tej funkcji jako wygodne rozwiązanie problemu losowości. Z doświadczenia zdobytego w pracy jako administrator MySQL wiem natomiast, że ORDER BY RAND to zło. Czy można wobec tego wierzyć sieci?

Podstawową sprawą jest własnoręczne przetestowanie wszelkich sugestii, nowinek i porad znalezionych w sieci. Przetestowanie na kopii zestawu danych, który jest używany produkcyjnie (na przykład na danych z kopii zapasowej). Przetestowanie na serwerze MySQL w tej samej wersji i tak samo skonfigurowanym jak serwer produkcyjny. Przetestowanie na platformie sprzętowej jak najbliższej platformie produkcyjnej. Trzeba także zrozumieć, co się dzieje na serwerze. Jak wygląda plan dotychczasowego zapytania a jak wygląda plan zapytania zmodyfikowanego? Co się zmieniło? Co się dzieje na serwerze podczas wykonywania tych zapytań? Ile rekordów jest odczytywanych, ile zapisywanych? Ile tablic tymczasowych jest tworzonych i gdzie? Trzeba przeprowadzić benchmark – sprawdzić maksymalną ilość starych zapytań, jakie wykonają się w czasie sekundy i porównać do ilości nowych.
Dopiero po takiej analizie możemy ocenić czy dana sugestia znaleziona w Google ma sens dla naszego zestawu danych obsługiwanego przez MySQL skonfigurowany przez nas i działający na naszym serwerze fizycznym.

W poprzednim poście pokazywałem, że SQL_CALC_FOUND_ROWS może być lepszym rozwiązaniem od COUNT(*), ale nie musi. Taka sama sytuacja występuje także w innych wypadkach. W sieci można na przykład znaleźć opinie, że MySQL kiepsko sobie radzi z podzapytaniami i lepiej jest zastępować je JOINami. Tyle że to nie zawsze jest prawdą. Może się okazać, że w danej sytuacji JOIN będzie kilkukrotnie wolniejszy niż podzapytanie i idąc za głosem sieci zrezygnujemy z najbardziej optymalnego zapytania nawet go nie testując. To nie tak, że jeśli autorem danej sugestii jest Peter Zaitsev, Baron Schwartz, Sheeri K. Cabral czy Mark Callaghan, to należy przyjąć ją bezkrytycznie. Każda modyfikacja zapytania, konfiguracji serwera, struktury bazy danych musi być poprzedzona dokładną analizą wydajności. To samo odnosi się do różnorakich problemów występujących na etapie projektowania bazy danych. Czy lepiej będzie zarządzać danymi przez triggery, czy też robić to samodzielnie, na poziomie aplikacji? Który silnik będzie lepszy? MyISAM czy InnoDB? Porządkować dane przy pomocy restrykcji nałożonych na klucze obce, czy samemu tego pilnować? Jeśli nie jesteś pewny, po prostu sprawdź. Wyzeruj statystyki serwera dla sesji, odpal jedno zapytanie. Zrzuć statystyki na bok. Wyzeruj. Odpal drugie zapytanie. Popatrz czym się różnią. Ilością odczytanych bloków z dysku? Ilością otwieranych rekordów? Przygotuj benchmark. Uruchom w pętli najpierw pierwsze zapytanie, potem drugie. Tak po sto – tysiąc – sto tysięcy razy. Zależy jak szybko działają. Sprawdź które wykonywało się szybciej i o ile. To jest podstawa, dlatego też jednymi z pierwszych moich postów były posty właśnie na ten temat (Profiling i Profiling ciąg dalszy).

Dość wynurzeń, następnym razem będą konkrety. Temat jednak jest na tyle istotny, że po prostu musiałem go rozwinąć.