2010-05-23 98 views
2

在學習瞭如何執行MySQL全文搜索之後,多表推薦的解決方案是OR MATCH,然後執行其他數據庫調用。你可以在我的查詢下面看到。MySQL「OR MATCH」在多個表上掛起(非常緩慢)

當我這樣做時,它只是處於「繁忙」狀態,而我無法訪問MySQL數據庫。

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 

任何幫助將不勝感激。


編輯

所有涉及的表是MyISAM數據,utf8_general_ci。

這裏的EXPLAIN SELECT語句:

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 

我不知道該怎麼做,看起來更整潔 - 關於


UPDATE

遺憾之後返回查詢196秒(我認爲是正確的)。沒有多個表的查詢大約需要0.5秒(我知道它非常慢,我們計劃儘快更改爲solr或sphinx),但是196秒?

如果我們能夠把號碼添加到相關性,如果它是在品牌名(d。name),這也將工作

+1

您的表格如何定義以及您使用的是哪種引擎?你能向我們展示你的「EXPLAIN SELECT ...」嗎? – ablaeul 2010-05-23 21:13:34

+0

我把EXPLAIN SELECT和引擎/排序,不知道如何顯示它的定義(我假設你在談論主表),除非你想要的結構?我應該給哪些桌子?謝謝! – 2010-05-23 23:18:17

回答

4

我發現兩件事大大減緩我的查詢和固定它們。

要回答第一個問題,它需要圍繞整個「對陣OR對陣」括號:

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) 
    ) 

我不知道如何使用EXPLAIN SELECT,但它幫了不少忙,所以謝謝您!這將第一個數字16076行減少到143個。然後我注意到另外兩個行數超過23和25000行。這是從該行的原因:

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

有一個原因,我被擺在首位,然後改變這樣做。當我改變了它,我不知道我可以做一個正常LEFT JOIN

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

這使我最終的查詢是這樣的:(和快得多從196秒來到0.0084左右)

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 

哦,甚至在我用多個表格進行全文搜索之前,它大概需要1/2秒。這是大大改善。