Php mysql查询执行耗时30秒…太长

Php mysql查询执行耗时30秒…太长,php,mysql,Php,Mysql,我正试图在一个站点上运行一个MySQL查询作为搜索,但这需要很长时间 我直接从phpMyAdmin运行它,大约需要20秒才能完成 以下是我正在运行的查询: SELECT * , bb_business.id AS bid FROM bb_business LEFT OUTER JOIN bb_offers ON bb_business.id = bb_offers.store_id LEFT OUTER JOIN bb_cat_business ON bb_business.id = bb_ca

我正试图在一个站点上运行一个MySQL查询作为搜索,但这需要很长时间

我直接从phpMyAdmin运行它,大约需要20秒才能完成

以下是我正在运行的查询:

SELECT * , bb_business.id AS bid
FROM bb_business
LEFT OUTER JOIN bb_offers ON bb_business.id = bb_offers.store_id
LEFT OUTER JOIN bb_cat_business ON bb_business.id = bb_cat_business.store_id
LEFT OUTER JOIN bb_categories ON bb_categories.id = bb_cat_business.cat_id
WHERE bb_business.active = '1'
AND (
bb_business.business_name LIKE '%altas%'
OR bb_categories.category_name LIKE '%altas%'
OR bb_business.business_name LIKE '%juice%'
OR bb_categories.category_name LIKE '%juice%'
)
AND (
bb_business.city LIKE '%%'
OR bb_business.state LIKE '%%'
OR bb_business.zip LIKE '%%'
)
GROUP BY bb_business.business_name
ORDER BY bb_business.business_name DESC 
LIMIT 1 , 10`
速度:显示行0-0 1总计,查询耗时20.1130秒

我不确定向您展示结构的最佳方式。但这里有一个复制粘贴,用于对某些表进行排序:

bb_ach            128 InnoDB latin1_swedish_ci 32.0 KB - 
bb_business       2,862 InnoDB latin1_swedish_ci 1.6 MB - 
bb_categories     15 MyISAM utf8_general_ci 6.7 KB 60 Bytes

bb_cat_business   2,926 MyISAM utf8_general_ci 49.6 KB 17 Bytes

bb_emails         13 MyISAM utf8_general_ci 6.0 KB - 
bb_member         409 MyISAM utf8_general_ci 62.7 KB - 
bb_member_card    593 MyISAM utf8_general_ci 112.1 KB - 
bb_merchant       154 InnoDB latin1_swedish_ci 32.0 KB - 
bb_offers         80 InnoDB latin1_swedish_ci 16.0 KB - 
bb_products       2 InnoDB latin1_swedish_ci 32.0 KB 
如果我能提供其他的东西。请让我知道

非常感谢你的帮助

编辑

好的,根据OMG小马的建议,我改变了一些事情。制作了一些MyISAM,并创建了一些全文索引供使用

我最后提出了这个问题:

SELECT *, bb_business.id AS bid FROM bb_business 
LEFT OUTER JOIN bb_offers ON bb_business.id = bb_offers.store_id 
LEFT OUTER JOIN bb_cat_business ON bb_business.id = bb_cat_business.store_id 
LEFT OUTER JOIN bb_categories ON bb_categories.id = bb_cat_business.cat_id 
WHERE bb_business.active = '1' AND 
MATCH(bb_business.business_name) AGAINST ('".addslashes($business)."') OR 
MATCH(bb_categories.category_name) AGAINST ('".addslashes($business)."') OR 
MATCH (bb_business.city,bb_business.state,bb_business.zip) AGAINST ('".addslashes($city)."') 
GROUP BY bb_business.business_name 
ORDER BY bb_business.imported,".$this->sortCol." ".$this->sortDirection." LIMIT ".$this->start.",".$this->limit
我认为这使它变得更慢

解释如下:

id  select_type  table  type  possible_keys  key  key_len  ref  rows  Extra  
1 SIMPLE bb_business ALL NULL NULL NULL NULL 2877 Using temporary; Using filesort 
1 SIMPLE bb_offers ALL NULL NULL NULL NULL 94   
1 SIMPLE bb_cat_business ALL NULL NULL NULL NULL 5697   
1 SIMPLE bb_categories eq_ref PRIMARY PRIMARY 8 buxback_site.bb_cat_business.cat_id 1 Using where 
因此,结果是第一个查询需要40秒才能完成。如果我再次搜索完全相同的短语,速度与我预期的MYSQL相同。以毫秒计。这只是第一次搜索,需要永远


还有什么想法吗?我很乐意花钱请人帮忙。

从表面上看,这是我的回复:

   SELECT *, bb_business.id AS bid
     FROM bb_business b
LEFT JOIN bb_offers o ON o.store_id = b.id
LEFT JOIN bb_cat_business cb ON cb.store_id = b.id
LEFT JOIN bb_categories c ON c.id = cb.cat_id
    WHERE b.active = '1'
      AND (    bb_business.business_name LIKE '%altas%'
            OR bb_business.business_name LIKE '%juice%'
            OR MATCH(c.category_name) AGAINST ('altas', 'juice'))          
 GROUP BY b.business_name
 ORDER BY b.business_name DESC 
    LIMIT 0, 10
限制从零开始-从一开始将忽略第一条记录。 您可以在MyISAM表上使用全文搜索FTS功能,这就是匹配的内容。。反对是。您可以通过添加全文索引使其更快。。。 选择*是一种不好的方法-最好把你真正想要的每一个都写出来
从表面上看,这是我的重写:

   SELECT *, bb_business.id AS bid
     FROM bb_business b
LEFT JOIN bb_offers o ON o.store_id = b.id
LEFT JOIN bb_cat_business cb ON cb.store_id = b.id
LEFT JOIN bb_categories c ON c.id = cb.cat_id
    WHERE b.active = '1'
      AND (    bb_business.business_name LIKE '%altas%'
            OR bb_business.business_name LIKE '%juice%'
            OR MATCH(c.category_name) AGAINST ('altas', 'juice'))          
 GROUP BY b.business_name
 ORDER BY b.business_name DESC 
    LIMIT 0, 10
限制从零开始-从一开始将忽略第一条记录。 您可以在MyISAM表上使用全文搜索FTS功能,这就是匹配的内容。。反对是。您可以通过添加全文索引使其更快。。。 选择*是一种不好的方法-最好把你真正想要的每一个都写出来
使用EXPLAIN查看发生了什么,数据库是如何执行数据库的


就像会降低性能一样,当参数以%开头时,数据库不能使用任何索引。

使用EXPLAIN查看发生了什么,数据库如何执行数据库


就像会破坏性能一样,当您的参数以%开头时,数据库不能使用任何索引。

只想返回并重新列出此项并发布答案。我最终创建了一个索引表,并创建了一个PHP脚本来索引主数据库。底线是MySQL没有很好地处理多个表中的多个匹配项。

只是想回来回顾一下并发布一个答案。我最终创建了一个索引表,并创建了一个PHP脚本来索引主数据库。底线是MySQL没有很好地处理多个表之间的多个匹配。

这些表上有什么索引?解释给出了什么?您知道吗,使用像“%”这样的字段与使用字段=“%”几乎是一样的,因为%%是转义百分号的方式。不确定这是否是你的意图。@Finster-而且它可能还强制对BBU业务进行全表扫描。。。最好完全从查询中删除任何此类条目。。。然后我们还有SELECT*而不是要检索的列列表,还有一个没有任何聚合列的GROUP BY。这些表上有哪些索引?解释给出了什么?您知道吗,使用像“%”这样的字段与使用字段=“%”几乎是一样的,因为%%是转义百分号的方式。不确定这是否是你的意图。@Finster-而且它可能还强制对BBU业务进行全表扫描。。。最好完全从查询中删除任何此类条目。。。然后我们还有SELECT*而不是要检索的列列表,和一个没有任何聚合列的组,你也可以移动你喜欢匹配的业务名称-against@ovais.tariq:全文支持仅在MyISAM表上-bb_business is Innodb您还可以移动business_name以匹配-against@ovais.tariq:全文支持仅在MyISAM表上-bb_业务是InnoDB