Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: optymalizacja zapytania SELECT
Forum PHP.pl > Forum > Bazy danych > MySQL
ktuvok
Mam następującą strukturę danych (uproszczenie):
  1. CREATE TABLE Konta (
  2. IDKonta INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. StatusKonta enum('N','E','B','Z','O','R') NOT NULL DEFAULT 'N',
  4. NumerKonta varchar(32) NOT NULL DEFAULT '',
  5. IDZakresu INT(11) UNSIGNED NOT NULL DEFAULT '0',
  6. KtoWpisal INT(11) UNSIGNED NOT NULL DEFAULT '0',
  7. DataWpisania DATETIME
  8. PRIMARY KEY (IDKonta),
  9. KEY IDZakresu (IDZakresu),
  10. KEY KtoWpisal (KtoWpisal),
  11. KEY DataWpisania (DataWpisania)
  12. ) TYPE=MyISAM
  13.  
  14. CREATE TABLE KontaKlientow (
  15. IDKombinacji INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  16. IDKlienta INT(11) UNSIGNED NOT NULL DEFAULT '0',
  17. IDKonta INT(11) UNSIGNED NOT NULL DEFAULT '0',
  18. PRIMARY KEY (IDKombinacji),
  19. KEY IDKlienta (IDKlienta),
  20. KEY IDKonta (IDKonta)
  21. ) TYPE=MyISAM COMMENT='powiązania Klienci - konta'
  22.  
  23. CREATE TABLE Klienci (
  24. IDKlienta INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  25. Nazwisko VARCHAR(30),
  26. Imie VARCHAR(30),
  27. PRIMARY KEY (IDKlienta),
  28. KEY Nazwisko (Nazwisko)
  29. ) TYPE=MyISAM
  30.  
  31. CREATE TABLE Uzytkownicy (
  32. IDUzytkownika INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  33. ImieINazwisko VARCHAR(40),
  34. PRIMARY KEY (IDUzytkownika)
  35. ) TYPE=MyISAM
  36.  
  37. CREATE TABLE Oddzialy (
  38. IDOddzialu INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  39. Nazwa1 VARCHAR(30),
  40. Nazwa2 VARCHAR(30),
  41. PRIMARY KEY (IDOddzialu)
  42. ) TYPE=MyISAM
  43.  
  44. CREATE TABLE Zakresy (
  45. IDZakresu INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  46. Nazwa VARCHAR(30),
  47. PRIMARY KEY (IDZakresu)
  48. ) TYPE=MyISAM

Wpisuję zapytanie:
  1. SELECT Konta.KtoWpisal, Konta.IDKonta, Konta.StatusKonta, Konta.NumerKonta, CONCAT_WS(' ', Klienci.Imie, Klienci.Nazwisko) AS NazwaKlienta,
  2. CONCAT_WS(' ', Oddzialy.Nazwa1, Odddzialy.Nazwa2) AS NazwaOddzialu, Oddzialy.IDOddzialu, Zakresy.IDZakresu
  3. FROM Konta, Klienci, Oddzialy, KontaKlientow, Uzytkownicy
  4. LEFT JOIN Zakresy ON Zakresy.IDZakresu = Konta.IDZakresu
  5. WHERE (DATE_FORMAT(Konta.DataWpisania,'%Y-%m-%d') BETWEEN '2004-09-01' AND '2004-09-30') AND Klienci.IDKlienta = KontaKlientow.IDKlienta AND KontaKlientow.IDKonta = Konta.IDKonta AND Uzytkownicy.IDUzytkownika = Konta.KtoWpisal AND Oddzialy.IDOddzialu = Uzytkownicy.IDOdddzialu

Zapytanie zwraca poprawną listę kont otwartych od w podanym zakresie dat.

Wszystko działa super, ale EXPLAIN dla tego zapytania zwraca coś takiego:
  1. TABLE konta
  2. type ALL
  3. possible_keys PRIMARY,KtoWpisal
  4. KEY NULL
  5. key_len NULL
  6. ref NULL
  7. rows 370
  8. Extra USING WHERE TABLE KontaKlientow
  9. type ALL
  10. possible_keys IDKlienta,IDRor
  11. KEY NULL
  12. key_len NULL
  13. ref NULL
  14. rows 50
  15. Extra USING WHERE

Dlaczego NULL? Dlaczego ALL?? Przecież wszystkie niezbędne pola są poindeksowane!
Potem jest już ok:
  1. TABLE klienci
  2. type eq_ref
  3. possible_keys PRIMARY
  4. KEY PRIMARY
  5. key_len 4
  6. ref kontaklientow.IDKlienta
  7. rows 1
  8. Extra
  9.  
  10. TABLE Uzytkownicy
  11. type eq_ref
  12. possible_keys PRIMARY, IDOddzialu
  13. KEY PRIMARY
  14. key_len 4
  15. ref Konta.KtoWpisal
  16. rows 1
  17. Extra
  18.  
  19. TABLE Odddzialy
  20. type eq_ref
  21. possible_keys PRIMARY, IDOddzialu
  22. KEY PRIMARY
  23. key_len 4
  24. ref Uzytkownicy.IDOddzialu
  25. rows 1
  26. Extra
  27.  
  28. TABLE Zakresy
  29. type eq_ref
  30. possible_keys PRIMARY, IDZakresu
  31. KEY PRIMARY
  32. key_len 4
  33. ref Konta.IDZakresu
  34. rows 1
  35. Extra USING INDEX

Pomóżcie - co należy zrobić, żeby aparat MySQL nie skanował całych dwóch pierwszych tabeli?

Pozdrawiam
Vertical
Spróbuj pozbyć się tego: "unsigned" i "default '0'"
ktuvok
Próbowałem, ale to bez znaczenia.

UNSIGNED określa, że w polu nie będzie nigdy wartości ujemnych i dzięki temu dwukrotnie zwiększa dostępny zakres wartości.
DEFAULT 0 będzie zawsze, jeśli wybiorę NOT NULL.

Pozdrawiam,
K
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.