# index: `review_count`, `store_id`, `status`, `name`, `address`
EXPLAIN ANALYZE SELECT
store0_.name,
store0_.status,
store0_.name,
store0_.address,
category1_.name
from
store store0_
inner join
category category1_
on store0_.category_id=category1_.category_id
left outer join
store_keyword storekeywo2_
on store0_.store_id=storekeywo2_.store_id
left outer join
keyword keyword3_
on storekeywo2_.keyword_id=keyword3_.keyword_id
where
store0_.review_count >= 0 AND ####
store0_.status='APPROVED'
AND store0_.name LIKE '가게%'
AND keyword3_.name = '분위기 좋은'
ORDER BY store0_.review_count
LIMIT 100
OFFSET 8000
字符串
如果您将条件“store0_.review_count >= 0 AND”,则性能将提高约10倍,从0.14ms提高到0.014ms。此时,实际时间是使用mysql(heidisql)的执行计划测量的。
(我不知道为什么在性能上会有这样的差异。)因为条件“store0_.review_count >= 0 AND”对所有行都是true。为什么性能提高了10倍?
3条答案
按热度按时间jvidinwx1#
这与性能优化无关,而是与查询的可读性/功能性有关:
AND keyword3_.name = '분위기 좋은'
。外部联接行没有关键字。它为null,因此您会忽略所有外部链接的数据列。看起来您确实需要一个内部连接,因此请使用内部连接而不是外部连接。WHERE
子句中而不是连接表来明确这一点。这也不会让读者知道您的查询是否会产生重复项。(不应该,因为安装了正确的密钥后,不应该将同一个关键字多次链接到一个商店。)review_count
在您的表中是唯一的吗?如果不是,则查询结果不具有确定性。可能是行7999、8000和8001具有相同的审阅计数。每次运行查询时,您可能会在结果中得到一行或另一行。如果您之前甚至运行过查询来获取前8000行,则在新选择的1000行中可能会有重复的行,而遗漏了其他行。使ORDER BY
子句具有确定性,例如ORDER BY store0_.review_count, store0_.store_id
的值。这是关于性能的:
下面是我可能编写此查询的方式:
字符串
MySQL 8提供了将元组与
>
进行比较的功能。如果您使用的是尚不支持此功能的旧版本,请将最后一个条件替换为:型
关于指数:当然,你必须能够快速找到一个关键字
型
这些是您可能已经拥有的索引。
然后,您希望对存储表进行索引,但有四列限制了行的访问:
现在,您需要一个索引,以便快速找到核心。如果90%的行为“已批准”,则该状态将没有太大帮助。如果只有0.9%的行为“已批准”,则将为“已批准”。如果大多数评论数是负面的,那么这是非常有选择性的,如果大多数是零或正面的,它不是。你希望有很多商店使用这个关键字还是很少?构建索引时,首先选择最具选择性的列,然后选择第二具选择性的列,依此类推。例如:
型
如果不安全,请使用不同的组合创建多个索引:
型
然后检查哪些正在使用,并删除其他的。
klh5stk12#
更好的索引可能是:
字符串
还有更多:
型
kuarbcqp3#
这些可能会有帮助。查看每个表的
SHOW CREATE TABLE
可能会有所帮助。字符串
WHERE (a,b) > (c,d)
的使用可能会优化,也可能不会优化; MySQL是什么版本?如果
store_keyword
是多对多Map表,请遵循 Many-to-many 中的索引建议LIMIT 100 OFFSET 8000
是一个性能杀手--它必须找到8100行,然后一次遍历8000行。如果你在“分页”,这是第81页--谁有耐心在列表中走那么远??想想另一种方式,给予用户访问如此庞大的列表。