Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> optymalizacja zapytania SELECT
ktuvok
post 27.09.2004, 14:19:09
Post #1





Grupa: Zarejestrowani
Postów: 243
Pomógł: 0
Dołączył: 30.11.2003

Ostrzeżenie: (0%)
-----


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

Ten post edytował ktuvok 27.09.2004, 16:11:56
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 2)
Vertical
post 27.09.2004, 18:07:56
Post #2





Grupa: Zarejestrowani
Postów: 848
Pomógł: 0
Dołączył: 7.07.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Spróbuj pozbyć się tego: "unsigned" i "default '0'"
Go to the top of the page
+Quote Post
ktuvok
post 27.09.2004, 20:58:36
Post #3





Grupa: Zarejestrowani
Postów: 243
Pomógł: 0
Dołączył: 30.11.2003

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 19.07.2025 - 10:15