这是我的查询,以17.9397秒的时间来获得响应:
SELECT allbar.iBarID AS iBarID,
allbar.vName AS vName,
allbar.tAddress AS tAddress,
allbar.tDescription AS tDescription,
(SELECT COUNT(*)
FROM tbl_post p
WHERE p.vBarIDs = allbar.iBarID) AS `total_post`,
allbar.bar_usbg AS bar_usbg,
allbar.bar_enhance AS bar_enhance,
(SELECT count(*)
FROM tbl_user
WHERE FIND_IN_SET(allbar.iBarID,vBarIDs)
AND (eType = 'bartender'
OR eType = 'Bar Manager'
OR eType = 'Bar Owner')) AS countAss,
allbar.eStatus AS eStatus
FROM
(SELECT disTINCT b.iBarID AS iBarID,
b.vName AS vName,
b.tAddress AS tAddress,
(CASE LENGTH(b.tDescription) WHEN 0 THEN '' WHEN LENGTH(b.tDescription) > 0
AND LENGTH(b.tDescription) < 50 THEN CONCAT(LEFT(b.tDescription, 50),'...') ELSE b.tDescription END) AS tDescription,
b.usbg AS bar_usbg,
b.enhance AS bar_enhance,
b.eStatus AS eStatus
FROM tbl_bar b,
tbl_user u
WHERE b.iBarID <> '-10') AS allbar
我试过EXPLAIN,这是结果:
任何人都可以解释这个EXPLAIN结果吗?
解决方法:
你应该完全重写那个查询,这完全是胡说八道.
在这一部分
(SELECT disTINCT b.<whatever>
FROM tbl_bar b,
tbl_user u
WHERE b.iBarID <> '-10') AS allbar
你基本上做的是将表tbl_bar中的每一行与tbl_user中的每一行连接起来.然后过滤tbl_bar,当选择所有内容时(也许MysqL必须在执行此操作之前将所有内容写入临时表中)返回结果集而不重复.你永远不想这样做.特别是当你甚至没有从tbl_user中选择任何东西时.有连接时,请指定它.如果没有,请不要加入这些表或创建连接.我不知道你的表是否或如何连接,但它应该是这样的:
(SELECT disTINCT b.<whatever>
FROM tbl_bar b
JOIN tbl_user u ON b.user_id = u.id /*or whatever the connection is*/
WHERE b.iBarID <> '-10') AS allbar
然后你有这个丑陋的子查询.
(SELECT COUNT(*)
FROM tbl_post p
WHERE p.vBarIDs = allbar.iBarID) AS `total_post`,
allbar.bar_usbg AS bar_usbg,
allbar.bar_enhance AS bar_enhance,
顺便说一下(参见你的解释输出).这意味着,对于外部查询的每一行执行此子查询(是的,如上所述,具有交叉连接的那一行).而不是这个子查询,加入外部查询中的表并使用GROUP BY.
到目前为止,查询应该如下所示:
SELECT
b.iBarID AS iBarID,
b.vName AS vName,
b.tAddress AS tAddress,
b.tDescription AS tDescription,
COUNT(*) AS `total_post`,
allbar.bar_usbg AS bar_usbg,
allbar.bar_enhance AS bar_enhance
FROM
tbl_bar b
JOIN tbl_user u ON b.user_id = u.id
JOIN tbl_post p ON p.vBarIDs = b.iBarID
WHERE b.iBarID <> '-10'
GROUP BY b.iBarID
(事实上,这是不对的.规则是,SELECT子句中的每一列也应该在GROUP BY子句中,或者具有聚合函数(如count()或max()应用于它.否则随机显示每个组的行.但这只是一个示例.您将需要计算详细信息.)
现在是最糟糕的部分.
(SELECT count(*)
FROM tbl_user
WHERE FIND_IN_SET(allbar.iBarID,vBarIDs)
AND (eType = 'bartender'
OR eType = 'Bar Manager'
OR eType = 'Bar Owner')) AS countAss,
allbar.eStatus AS eStatus
使用FIND_IN_SET()表明,您将多个值存储在一列中.再一次,你永远不想那样做.请阅读此answer to Is storing a delimited list in a database column really that bad?
,然后重新设计您的数据库.我不会帮你这个,因为这显然是一个单独的问题的东西.
所有这些并没有真正解释EXPLAIN的结果.对于这个问题,我将不得不写一个完整的教程,我不会这样做,因为一切都在manual,一如既往.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。