2017-03-25 1 views
0

Ich habe einige Probleme mit einigen MySQL-Abfragen etwa 50 Sekunden dauern einige Male auszuführen, aber auch andere Zeiten seine etwa 1 Sekunde. Die Abfrage tut, was ich brauche, ist aber offensichtlich zu langsam.Beschleunigung PHP/MySQL Abfrage/korrekte Verwendung von Joins?

Im Folgenden sind die drei Tabellen, die verwendet werden, und einige der Säulen:

Produkte Tabelle (14315 Zeilen)

id | title | image | price | rrp | upsell 
20381 | test | test | 24.00 | 30.00 | 1 

product_to_category Tabelle (26283 Zeilen)

ptc_id | product_id | category_id 
33797 | 20381  | 29 

category_description Tabelle (29 Zeilen)

category_id | name  | url_slug 
29   | Kitchens | kitchen-products 

seo_slugs Tabelle (14898 Zeilen)

seo_slug_id | route   | seo_slug 
26987  | product=20381 | test-product-kitchen-area-2000-500 

Im Folgenden finden Sie die aktuellen codeigniter Funktionen ich verwende.

public function getUpsells() { 
$this->db->select('products.id, products.title, products.image, products.category, products.price, products.rrp', FALSE); 
$this->db->from('product_to_category'); 
$this->db->join('products', 'products.id = product_to_category.product_id'); 
$this->db->join('category_description', 'category_description.category_id = product_to_category.category_id'); 
$this->db->join('seo_slugs', 'seo_slugs.route = concat(\'product=\', product_to_category.product_id)'); 
$this->db->where('products.upsell',1); 
$this->db->where('products.status',1); 
$this->db->group_by('product_to_category.product_id'); 
$query = $this->db->get(); 
return $query->result(); 

} Ich bin die Hoffnung, jemand mich in der richtigen Richtung zeigen kann und raten, wo ich falsch gehe. Es ist ehrlich das erste Mal zu sein, die ich verwendet habe in einer Abfrage verknüpft und obwohl es scheint zu funktionieren, ist es in der Regel sehr langsam, wenn zuerst die Seite geladen wird, dann, wenn aktualisiert etc scheint es ziemlich schnell zu laden.

Unten finden Sie die Abfrage läuft:

SELECT products.id, products.title, products.image, products.category, products.price, products.rrp 
FROM `product_to_category` 
JOIN `products` ON `products`.`id` = `product_to_category`.`product_id` 
JOIN `category_description` ON `category_description`.`category_id` = `product_to_category`.`category_id` 
JOIN `seo_slugs` ON `seo_slugs`.`route` = concat('product=', product_to_category.product_id) 
WHERE `products`.`upsell` = 1 
AND `products`.`status` = 1 
GROUP BY `product_to_category`.`product_id` 

Profilierungsergebnis:

Starting 18 µs 
Waiting For Query Cache Lock 5 µs 
Checking Query Cache For Query 48 µs 
Checking Permissions 5 µs 
Checking Permissions 4 µs 
Checking Permissions 4 µs 
Checking Permissions 5 µs 
Opening Tables 20 µs 
System Lock 9 µs 
Waiting For Query Cache Lock 15 µs 
Init 25 µs 
Optimizing 13 µs 
Statistics 23 µs 
Preparing 19 µs 
Creating Tmp Table 21 µs 
Executing 5 µs 
Copying To Tmp Table 51.8 s 
Sorting Result 26 µs 
Sending Data 24 µs 
End 9 µs 
Removing Tmp Table 33 µs 
End 7 µs 
Query End 7 µs 
Closing Tables 14 µs 
Freeing Items 12 µs 
Waiting For Query Cache Lock 6 µs 
Freeing Items 11 µs 
Waiting For Query Cache Lock 7 µs 
Freeing Items 7 µs 
Storing Result In Query Cache 162 µs 
Logging Slow Query 6 µs 
Logging Slow Query 38 µs 
Cleaning Up 7 µs 

ERKLÄREN Ergebnis:

+----+-------------+----------------------+--------+---------------+---------+---------+-----------------------------------------------------+-------+---------------------------------+ 
| id | select_type |  table   | type | possible_keys | key | key_len |       ref       | rows |    Extra    | 
+----+-------------+----------------------+--------+---------------+---------+---------+-----------------------------------------------------+-------+---------------------------------+ 
| 1 | SIMPLE  | seo_slugs   | ALL | NULL   | NULL | NULL | NULL            | 14958 | Using temporary; Using filesort | 
| 1 | SIMPLE  | product_to_category | ALL | category_id | NULL | NULL | NULL            | 26343 | Using where; Using join buffer | 
| 1 | SIMPLE  | category_description | eq_ref | PRIMARY  | PRIMARY | 4  | wilsonar_hcsupplies.product_to_category.category_id |  1 | Using index      | 
| 1 | SIMPLE  | products    | eq_ref | PRIMARY,id | PRIMARY | 4  | wilsonar_hcsupplies.product_to_category.product_id |  1 | Using where      | 
+----+-------------+----------------------+--------+---------------+---------+---------+-----------------------------------------------------+-------+---------------------------------+ 
+1

Bearbeiten Sie Ihre Frage und zeigen Sie die Abfrage mit * qualifizierten * Spaltennamen an. Wir haben jetzt Ihre Daten nicht, also wissen wir nicht, wo die Spalten kämmen. –

+0

Haben Sie Indizes gesetzt? Wie wäre es mit einer Ansicht? Eines ist sicher: Concat ist normalerweise ziemlich langsam. – Jeff

+1

Zeigen Sie uns die EXPLAIN Ihrer Anfrage –

Antwort

0

ERKLÄREN sagt uns, dass product_to_category einen Index hat, dass MySQL hält mit , da mains_keys "category_id" ist. Es wird jedoch aus irgendeinem Grund nicht verwendet.

„Reihen“ ist 26343 und „Schlüssel“ ist NULL, was bedeutet, MySQL alle 26343 Zeilen in product_to_category für jedes Produkt scannen, die sogar die Puffer Optimierung verbinden mit horrenden sein wird.

product_to_category Table (26283 rows) 
ptc_id | product_id | category_id 
33797 | 20381  | 29 

ptc_id ist nutzlos, da der Primärschlüssel dieser Tabelle (category_id, product_id) sein sollte, mit einem eindeutigen Index auf (product_id, category_id) hinzugefügt Suche zu optimieren. Das macht mich der Datenbankstruktur verdächtig, deshalb werde ich darauf wetten, dass der Designer die falsche Art verwendet (dh alles außer INT) für eine der Spalten in einem der Tische. Also, überprüfen Sie Ihre Spaltentypen für Tinyint, Smallint, Bigint, unsigned, was auch immer ...

Andere Ursachen wäre, dass der Index namens category_id tatsächlich die Spalte category_id nicht indiziert. Man weiß nie. Bitte prüfe.

Nun gibt es ein weiteres Problem mit der Abfrage, nämlich, dass die GROUP BY die gesamte Abfrage nutzlos macht. Ich frage mich, was diese Abfrage tun soll ...

0

(ich habe noch ein brauchbares „Profil“ zu sehen.)

Auch ohne die Tabellenstruktur von product_to_category zu sehen, vermute ich, dass es der defizitäre Teil ist.

  • Befreien wenn ptc_id
  • Wechsel zu PRIMARY KEY(product_id, category_id)
  • Auch INDEX(category_id, product_id)

Further discussion der optimal viele haben: viel Zuordnungstabelle.

Auch haben INDEX(upsell, status). Dieser zusammengesetzte Index kann oder kann nicht verwendet werden, abhängig von der Kardinalität dieser Spalten. Wenn nützlich, wird es sehr vorteilhaft sein. Wenn nicht, dann ist ein Tabellenscan notwendig.

Und loswerden der letzten zwei join() s - Sie verwenden diese Tabelle nicht. MySQL verbindet sich damit, um sicherzustellen, dass sie existieren, aber dabei Zeit verschwenden. Wenn Sie die zwei unnötigen Tabellen loswerden, können Sie die GROUP BY loswerden.

Aber warum dann überhaupt berühren categories? Das loswerden, wird products_to_categories los.

Also das ist alles, was Sie ist der obige Index benötigt, zuzüglich

SELECT id, title, image, category, price, rrp 
FROM `products` 
WHERE `upsell` = 1 
    AND `status` = 1 

Aber warten! Das wird nicht funktionieren, weil es keine products.category gibt.

Warum manchmal schnell? Sie haben den "Query Cache" aktiviert. Wenn Sie die identische Abfrage ein zweites Mal vor alle Änderungen an alle der relevanten Tabellen ausführen, wird es von der QC abgerufen werden, in der Regel in einer Millisekunde oder so.

Verwandte Themen