【问题标题】:MySQL "OR MATCH" hangs (very slow) on multiple tablesMySQL“OR MATCH”在多个表上挂起(非常慢)
【发布时间】:2010-05-23 08:03:11
【问题描述】:

在学习了如何进行 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

我不知道如何让它看起来更整洁 -- 抱歉


更新

它在 196 秒后返回查询(我认为是正确的)。没有多个表的查询大约需要 0.56 秒(我知道这真的很慢,我们计划很快更改为 solr 或 sphinx),但需要 196 秒??

如果我们可以在品牌名称中添加一个数字(d.name),那也可以

【问题讨论】:

  • 您的表是如何定义的,您使用的是哪个引擎?你能告诉我们你的EXPLAIN SELECT...吗?
  • 我把 EXPLAIN SELECT 和引擎/排序规则,不知道如何显示它是如何定义的(我假设你在谈论主表),除非你想要结构?我应该给哪些表?谢谢!

标签: mysql full-text-search


【解决方案1】:

我发现 2 件事情大大降低了我的查询速度并修复了它们。

要回答第一个问题,它需要在整个“MATCH AGAINST OR MATCH AGAINST”周围加上括号:

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 秒。这已经大大改善了。

【讨论】:

    猜你喜欢
    • 2016-09-22
    • 1970-01-01
    • 2022-01-25
    • 2013-06-19
    • 2015-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-24
    相关资源
    最近更新 更多