2 Stimmen

MySQL "OR MATCH" bleibt bei mehreren Tabellen hängen (sehr langsam)

Nachdem ich gelernt hatte, wie man eine MySQL-Volltextsuche durchführt, war die empfohlene Lösung für mehrere Tabellen OR MATCH und führen dann den anderen Datenbankaufruf durch. Sie können das in meiner Abfrage unten sehen.

Wenn ich dies tue, bleibt es im Status "beschäftigt" stecken und ich kann nicht auf die MySQL-Datenbank zugreifen.

SELECT 
 a.`product_id`, a.`name`, a.`slug`, a.`description`, b.`list_price`, b.`price`, c.`image`, c.`swatch`, e.`name` AS industry, 
 MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE )     AS relevance 
FROM 
 `products` AS a LEFT JOIN `website_products` AS b 
  ON (a.`product_id` = b.`product_id`) 
 LEFT JOIN ( SELECT `product_id`, `image`, `swatch` FROM `product_images` WHERE `sequence` = 0) AS c 
  ON (a.`product_id` = c.`product_id`) 
 LEFT JOIN `brands` AS d 
  ON (a.`brand_id` = d.`brand_id`) 
 INNER JOIN `industries` AS e ON (a.`industry_id` = e.`industry_id`) 
WHERE 
 b.`website_id` = %d
 AND b.`status` = %d
 AND b.`active` = %d 
 AND MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE ) 
  OR MATCH ( d.`name` ) AGAINST ( '%s' IN BOOLEAN MODE )
GROUP BY a.`product_id` 
ORDER BY relevance DESC 
LIMIT 0, 9 

Für jede Hilfe wären wir Ihnen sehr dankbar.


EDIT

Alle betroffenen Tabellen sind MyISAM, utf8_general_ci.

Hier ist die EXPLAIN SELECT-Anweisung:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 16076 Using temporary; Using filesort
1 PRIMARY b ref product_id product_id 4 database.a.product_id 2  
1 PRIMARY e eq_ref PRIMARY PRIMARY 4 database.a.industry_id 1  
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 23261  
1 PRIMARY d eq_ref PRIMARY PRIMARY 4 database.a.brand_id 1 Using where
2 DERIVED product_images ALL NULL NULL NULL NULL 25933 Using where

Ich weiß nicht, wie ich das besser aussehen lassen kann - tut mir leid.


UPDATE

wird die Abfrage nach 196 Sekunden zurückgegeben (ich glaube, das ist richtig). Die Abfrage ohne mehrere Tabellen dauert etwa 0,56 Sekunden (was ich weiß, ist wirklich langsam, wir planen auf Solr oder Sphinx bald ändern), aber 196 Sekunden?

Wenn wir der Relevanz eine Zahl hinzufügen könnten, wenn sie im Markennamen enthalten wäre ( d. name ), das würde auch funktionieren

4voto

Kerry Jones Punkte 21572

Ich habe 2 Dinge gefunden, die meine Abfrage drastisch verlangsamen, und sie behoben.

Um das erste Problem zu lösen, musste das gesamte "MATCH AGAINST OR MATCH AGAINST" in Klammern gesetzt werden:

WHERE 
    b.`website_id` = %d
    AND b.`status` = %d
    AND b.`active` = %d 
    AND ( 
        MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE ) 
        OR MATCH ( d.`name` ) AGAINST ( '%s' IN BOOLEAN MODE )
    )

Ich habe nicht verstanden, wie man EXPLAIN SELECT aber es hat mir sehr geholfen, also vielen Dank! Dadurch wurde die erste Zahl von 16076 Zeilen auf 143 reduziert. Dann fielen mir die beiden anderen mit über 23 und 25 Tausend Zeilen auf. Das war die Ursache für diese Zeile:

LEFT JOIN ( SELECT `product_id`, `image`, `swatch` FROM `product_images` WHERE `sequence` = 0) AS c 
    ON (a.`product_id` = c.`product_id`)

Es gab einen Grund, warum ich das überhaupt gemacht habe, der sich dann geändert hat. Als ich es änderte, wusste ich nicht, dass ich eine normale LEFT JOIN :

LEFT JOIN `product_images` AS c 
    ON (a.`product_id` = c.`product_id`)

Dies macht meine endgültige Abfrage wie folgt: (und viel schneller ging von der 196 Sekunden auf 0,0084 oder so)

SELECT 
    a.`product_id`, a.`name`, a.`slug`, a.`description`, b.`list_price`, b.`price`, 
    c.`image`, c.`swatch`, e.`name` AS industry, 
    MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE ) AS relevance 
FROM 
    `products` AS a LEFT JOIN `website_products` AS b 
        ON (a.`product_id` = b.`product_id`) 
    LEFT JOIN `product_images` AS c 
        ON (a.`product_id` = c.`product_id`) 
    LEFT JOIN `brands` AS d 
        ON (a.`brand_id` = d.`brand_id`) 
    INNER JOIN `industries` AS e 
        ON (a.`industry_id` = e.`industry_id`) 
WHERE 
    b.`website_id` = %d
    AND b.`status` = %d
    AND b.`active` = %d
    AND c.`sequence` = %d
    AND ( 
        MATCH( a.`name`, a.`sku`, a.`description` ) AGAINST ( '%s' IN BOOLEAN MODE ) 
        OR MATCH( d.`name` ) AGAINST( '%s' IN BOOLEAN MODE ) 
    )
GROUP BY a.`product_id` 
ORDER BY relevance DESC 
LIMIT 0, 9

Oh, und sogar bevor ich eine Volltextsuche mit mehreren Tabellen durchführte, dauerte es etwa 1/2 Sekunde. Das ist jetzt viel besser.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X