Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Optymalizacja zapytania
Forum PHP.pl > Forum > Bazy danych > MySQL
kmkm2
Witam, potrzebuję pomocy przy optymalizacjia zapytania. Zapytania co prawda działa, ale jest bardzo wolne. Proszę o wskazówki w rozwiązaniu problemu.
Struktura tabel:

  1. -- phpMyAdmin SQL Dump
  2. -- version 4.2.6deb1
  3. -- <a href="http://www.phpmyadmin.net" target="_blank">http://www.phpmyadmin.net</a>
  4. --
  5. -- Host: localhost
  6. -- Czas generowania: 14 Lut 2015, 15:45
  7. -- Wersja serwera: 5.5.37-0ubuntu0.13.10.1
  8. -- Wersja PHP: 5.5.3-1ubuntu2.6
  9.  
  10. SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
  11. SET time_zone = "+00:00";
  12.  
  13.  
  14. /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
  15. /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
  16. /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
  17. /*!40101 SET NAMES utf8 */;
  18.  
  19. --
  20. -- Baza danych: `electro1_serwis`
  21. --
  22.  
  23. DELIMITER $$
  24. --
  25. -- Funkcje
  26. --
  27. CREATE DEFINER=`electro1`@`localhost` FUNCTION `fn_GetYearAlbumRank`(parmAlbumID INT, parmYear INT) RETURNS int(11)
  28. BEGIN
  29. DECLARE retval INT;
  30. SELECT 5 INTO retval;
  31. RETURN retval;
  32. END$$
  33.  
  34. CREATE DEFINER=`electro1`@`localhost` FUNCTION `get_status`(`id_zlecenia` INT) RETURNS int(11)
  35. NO SQL
  36. BEGIN
  37. DECLARE tmp int;
  38. SELECT id_stan_zlecenia INTO tmp FROM `stan_zlecenia` WHERE stan_zlecenia.id_zlecenia=id_zlecenia ORDER BY id_stan_zlecenia DESC LIMIT 1;
  39. RETURN tmp;
  40. END$$
  41.  
  42. DELIMITER ;
  43.  
  44. -- --------------------------------------------------------
  45.  
  46. --
  47. -- Struktura tabeli dla tabeli `klienci`
  48. --
  49.  
  50. CREATE TABLE IF NOT EXISTS `klienci` (
  51. `id_klienci` int(11) NOT NULL,
  52. `imienazwisko` varchar(200) COLLATE utf8_polish_ci NOT NULL,
  53. `nazwisko` varchar(200) COLLATE utf8_polish_ci NOT NULL,
  54. `adres` varchar(100) COLLATE utf8_polish_ci NOT NULL,
  55. `miasto` varchar(50) COLLATE utf8_polish_ci NOT NULL,
  56. `telefon` varchar(20) COLLATE utf8_polish_ci NOT NULL,
  57. `nip` varchar(20) COLLATE utf8_polish_ci NOT NULL,
  58. `mail` varchar(200) COLLATE utf8_polish_ci NOT NULL,
  59. `firma` varchar(200) COLLATE utf8_polish_ci NOT NULL
  60. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1375 ;
  61.  
  62. -- --------------------------------------------------------
  63.  
  64. --
  65. -- Struktura tabeli dla tabeli `stan_zlecenia`
  66. --
  67.  
  68. CREATE TABLE IF NOT EXISTS `stan_zlecenia` (
  69. `id_stan_zlecenia` int(11) NOT NULL,
  70. `id_zlecenia` int(11) NOT NULL,
  71. `uwagi` text COLLATE utf8_polish_ci NOT NULL,
  72. `id_statusy` int(11) NOT NULL,
  73. `data_status` int(11) NOT NULL
  74. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=3144 ;
  75.  
  76. -- --------------------------------------------------------
  77.  
  78. --
  79. -- Struktura tabeli dla tabeli `statusy`
  80. --
  81.  
  82. CREATE TABLE IF NOT EXISTS `statusy` (
  83. `id_statusy` int(11) NOT NULL,
  84. `status` varchar(50) COLLATE utf8_polish_ci NOT NULL,
  85. `kolor` varchar(7) COLLATE utf8_polish_ci NOT NULL,
  86. `waga` int(11) NOT NULL,
  87. `termin` tinyint(4) NOT NULL,
  88. `widoczny` tinyint(4) NOT NULL
  89. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=14 ;
  90.  
  91. -- --------------------------------------------------------
  92.  
  93. --
  94. -- Struktura tabeli dla tabeli `zlecenia`
  95. --
  96.  
  97. CREATE TABLE IF NOT EXISTS `zlecenia` (
  98. `id_zlecenia` int(11) NOT NULL,
  99. `id_klienci` int(11) NOT NULL,
  100. `id_logowanie` int(11) NOT NULL,
  101. `rodzaj_sprzetu` varchar(50) COLLATE utf8_polish_ci NOT NULL,
  102. `model` varchar(200) COLLATE utf8_polish_ci NOT NULL,
  103. `numer_seryjny` varchar(200) COLLATE utf8_polish_ci NOT NULL,
  104. `producent` varchar(200) COLLATE utf8_polish_ci NOT NULL,
  105. `wyposazenie_dodatkowe` varchar(200) COLLATE utf8_polish_ci NOT NULL,
  106. `opis_usterki` text COLLATE utf8_polish_ci NOT NULL,
  107. `przyczyna_usterki` varchar(50) COLLATE utf8_polish_ci NOT NULL,
  108. `proba_naprawy` tinyint(1) NOT NULL,
  109. `uwagi` varchar(200) COLLATE utf8_polish_ci NOT NULL,
  110. `max_koszt_naprawy` int(11) NOT NULL,
  111. `data` int(11) NOT NULL,
  112. `kto` varchar(20) COLLATE utf8_polish_ci NOT NULL,
  113. `ladowarka` tinyint(1) NOT NULL,
  114. `torba` tinyint(1) NOT NULL,
  115. `dysk` tinyint(1) NOT NULL,
  116. `bateria` double NOT NULL,
  117. `przyczyna` enum('samoistna','upadek','zalanie','inna') COLLATE utf8_polish_ci NOT NULL,
  118. `dostarczenie` enum('osobiscie','kurier','samwysylka') COLLATE utf8_polish_ci NOT NULL,
  119. `priorytet` enum('bezplatna','platna','express','') COLLATE utf8_polish_ci NOT NULL,
  120. `archiwum` tinyint(1) NOT NULL,
  121. `login_allegro` varchar(50) COLLATE utf8_polish_ci NOT NULL,
  122. `nr_aukcji_allegro` varchar(20) COLLATE utf8_polish_ci NOT NULL
  123. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=2010 ;
  124.  
  125. --
  126. -- Indeksy dla zrzutów tabel
  127. --
  128.  
  129. --
  130. -- Indexes for table `klienci`
  131. --
  132. ALTER TABLE `klienci`
  133. ADD PRIMARY KEY (`id_klienci`);
  134.  
  135. --
  136. -- Indexes for table `stan_zlecenia`
  137. --
  138. ALTER TABLE `stan_zlecenia`
  139. ADD PRIMARY KEY (`id_stan_zlecenia`);
  140.  
  141. --
  142. -- Indexes for table `statusy`
  143. --
  144. ALTER TABLE `statusy`
  145. ADD PRIMARY KEY (`id_statusy`);
  146.  
  147. --
  148. -- Indexes for table `zlecenia`
  149. --
  150. ALTER TABLE `zlecenia`
  151. ADD PRIMARY KEY (`id_zlecenia`);
  152.  
  153. --
  154. -- AUTO_INCREMENT for dumped tables
  155. --
  156.  
  157. --
  158. -- AUTO_INCREMENT dla tabeli `klienci`
  159. --
  160. ALTER TABLE `klienci`
  161. MODIFY `id_klienci` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1375;
  162. --
  163. -- AUTO_INCREMENT dla tabeli `stan_zlecenia`
  164. --
  165. ALTER TABLE `stan_zlecenia`
  166. MODIFY `id_stan_zlecenia` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3144;
  167. --
  168. -- AUTO_INCREMENT dla tabeli `statusy`
  169. --
  170. ALTER TABLE `statusy`
  171. MODIFY `id_statusy` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=14;
  172. --
  173. -- AUTO_INCREMENT dla tabeli `zlecenia`
  174. --
  175. ALTER TABLE `zlecenia`
  176. MODIFY `id_zlecenia` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2010;
  177. /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
  178. /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
  179. /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
  180.  


Zapytanie:
  1. $sql="SELECT *
  2. FROM klienci
  3. INNER JOIN zlecenia
  4. USING ( `id_klienci` )
  5. LEFT OUTER JOIN (
  6. SELECT statusy.status,statusy.termin, stan_zlecenia.id_statusy, stan_zlecenia.id_zlecenia, stan_zlecenia.data_status, stan_zlecenia.uwagi, statusy.waga
  7. FROM `stan_zlecenia` , `statusy`
  8. WHERE stan_zlecenia.id_statusy = statusy.id_statusy
  9. ) AS sz
  10.  
  11. USING ( `id_zlecenia` )
  12.  
  13. INNER JOIN logowanie
  14. USING( `id_logowanie` )
  15.  
  16. WHERE 1 $sql_wyszukiwanie $sql_logowanie
  17. AND (
  18.  
  19. sz.data_status IS NULL
  20. OR
  21. sz.data_status = ( SELECT MAX( data_status ) AS max_data FROM stan_zlecenia WHERE stan_zlecenia.id_zlecenia = zlecenia.id_zlecenia )
  22.  
  23. )
  24.  
  25. ORDER BY waga,data_status DESC $limit";
Pyton_000
jest wolne bo w tabelach nie masz pozakładanych indeksów.

Pozakładaj indeksy na kolumny którymi łączysz tabele. Do tego na kolumny: id_klienci, id_stan_zlecenia, id_statusy, id_zlecenia załóż PrimaryKey
kmkm2
Indexy, są pozakładane. Zmodyfikowałem pierwszy, dołączyłem pełną definicje tabel.
sazian
EXPLAIN sprzed selektem i pokaż wynik
kmkm2
Pomogła zmiana podzapytania z
  1. SELECT MAX( data_status ) AS max_data FROM stan_zlecenia WHERE stan_zlecenia.id_zlecenia = zlecenia.id_zlecenia )
na
  1. SELECT data_status FROM stan_zlecenia WHERE stan_zlecenia.id_zlecenia = zlecenia.id_zlecenia ORDER BY `id_stan_zlecenia` DESC LIMIT 1
.

Wynik explain:




id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2812 Using where; Using temporary; Using filesort
1 PRIMARY logowanie ALL PRIMARY NULL NULL NULL 2 Using join buffer
1 PRIMARY zlecenia eq_ref PRIMARY PRIMARY 4 sz.id_zlecenia 1 Using where
1 PRIMARY klienci eq_ref PRIMARY PRIMARY 4 electro1_serwis.zlecenia.id_klienci 1
3 DEPENDENT SUBQUERY stan_zlecenia ref id_zlecenia id_zlecenia 4 electro1_serwis.zlecenia.id_zlecenia 1 Using where; Using filesort
2 DERIVED statusy ALL PRIMARY NULL NULL NULL 12
2 DERIVED stan_zlecenia ref id_statusy id_statusy 4 electro1_serwis.statusy.id_statusy 75
sazian
ile rekordów jest wynikiem tego zapytania ?
jak bardzo jest wolne ?
tego OR'a z linij 20 pewnie nie możesz się pozbyć ? bo najprawdopodobniej to on wszytko psuje
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.