Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Powolne zapytanie Mysql:JOIN + wiele WHERES + ORDER BY

Indeksy robią ogromną różnicę w mysql, jedno zapytanie, które zajęło 15 minut z niewłaściwym zestawem indeksów, zajęło 0,2 sekundy z właściwymi, ale znalezienie właściwej równowagi jest generalnie problemem. Oczywiście bez niektórych przykładowych danych naprawdę trudno powiedzieć, czy poniższe rozwiązanie pozwoli Ci zaoszczędzić czas, ale teoretycznie powinno.

Aby odpowiedzieć na Twoje pytania, przeprojektowałbym tabele w następujący sposób:

CREATE TABLE `product_all` ( 
`prod_id` INT( 10 ) NOT NULL, 
`ref_id` INT( 10) NOT NULL, 
`date` DATE NOT NULL , 
`buy_link` BLOB NOT NULL , 
`sale_price` FLOAT NOT NULL,
PRIMARY KEY (prod_id, ref_id) ,
INDEX date_Index (`date` ASC),
UNIQUE INDEX prod_price_Index (prod_id ASC, sale_price ASC)
) ENGINE = MYISAM ; 


CREATE TABLE `product_info` ( 
`prod_id` INT( 10 ) NOT NULL AUTO_INCREMENT, 
`prod_name` VARCHAR( 200 ) NOT NULL, 
`brand` VARCHAR( 50 ) NOT NULL, 
`retail_price` FLOAT NOT NULL, 
`category` INT( 3 ) NOT NULL, 
`gender` VARCHAR( 1 ) NOT NULL, 
`type` VARCHAR( 10 ) NOT NULL,
PRIMARY KEY (prod_id) ,
UNIQUE INDEX prod_id_name_Index (prod_id ASC, prod_name ASC),
INDEX category_Index (category ASC),
INDEX gender_Index (gender ASC)
) ENGINE = MYISAM ;

SELECT product_info.*, MIN(product_all.sale_price) as sale_price, product_all.buy_link         
FROM product_info         
NATURAL JOIN (SELECT * FROM product_all WHERE product_all.date = '2010-09-30') as product_all         
WHERE (product_info.category = 2           
AND product_info.gender = 'W' )         
GROUP BY product_all.prod_id         
ORDER BY MIN(product_all.sale_price) ASC LIMIT 13        

Zwiększenie wydajności tutaj uzyskuje się przez indeksowanie głównych pól, które są łączone i są opisane w klauzuli WHERE. Osobiście wybrałbym twoje pierwsze zapytanie, gdy myślisz o tym, które powinno działać lepiej.

O ile rozumiem, co się dzieje w pierwszym i drugim zapytaniu:

  • Pierwsze zapytanie jest filtrowane przez podzapytanie przed wykonaniem naturalnego złączenia, co oznacza, że ​​łączy się tylko w wynikowych danych, a nie w całej tabeli.
  • Drugie zapytanie łączy całą drugą tabelę, a następnie filtruje wynikowe wiersze całej partii z powrotem do tego, co chcesz.

Zasadniczo zwykle chcesz dodać indeksy do głównych pól łączących, a także pól, których najczęściej używasz w klauzulach where. Umieściłem również kilka unikalnych indeksów w niektórych polach, które chcesz regularnie sprawdzać, takich jak prod_id_name_Index.

Jeśli to nie poprawi twojej wydajności, jeśli możesz opublikować jakieś fałszywe dane do zabawy, być może będę w stanie uzyskać szybsze rozwiązanie, które mogę przetestować.

Tutaj to artykuł, który przechodzi przez indeksowanie pod kątem wydajności w mysql, warto przeczytać, jeśli chcesz dowiedzieć się więcej.

Powodzenia!

EDYCJA:Twoje ostatnie pytanie, które przegapiłem za pierwszym razem, odpowiedź brzmi, że jeśli indeksujesz główne pola łączące, a następnie zmienisz miejsce, w którym wpłynie tylko nieznacznie na ogólną wydajność, ale unikalne indeksy, które umieściłem na tabelach, powinny uwzględniać większość rzeczy, na których będziesz chciał opierać zapytania. Najważniejszą rzeczą do zapamiętania jest to, że jeśli często wysyłasz zapytania lub dołączasz do pola, powinno ono być naprawdę zaindeksowane, ale drobne zapytania i zmiany w kolejności przez Ciebie nie powinny po prostu martwić się o ponowne wyrównanie strategii indeksowania.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Używając Pythona szybko wstawiaj wiele kolumn do Sqlite\Mysql

  2. Mysql Dołącz do dwóch stołów na klawiszach

  3. Symfony+Doctrine:Poprawna składnia YAML dla domyślnej wartości pola logicznego

  4. Funkcja MySQL do obliczania odległości między dwiema szerokościami i długościami geograficznymi

  5. Czy lepiej WYBRAĆ przed DOŁĄCZENIEM?