我有一个join查询,需要花费很多时间来处理。
SELECT
COUNT(c.id)
FROM `customers` AS `c`
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`id`
LEFT JOIN `customer_extra` AS `cx` ON `c`.`id` = `cx`.`customer_id`
LEFT JOIN `customers_address` AS `ca` ON `ca`.`id` = `cx`.`customer_default_address_id`
LEFT JOIN `lytcustomer_tier` AS `ct` ON `cx`.`lyt_customer_tier_id` = `ct`.`id`
WHERE (c.shop_id = '12121') AND ((DATE(cx.last_email_open_date) > '2019-11-08'));
这主要是因为表“customers”有200万条记录。
我可以进入索引等,但更大的一点是,这250万可能成为一个十亿记录一天。
我正在寻找能够提高性能的解决方案。我考虑过
a) 横向可扩展性:将mysql表分配到不同的部分,并独立地查询计数。
b) 使用综合指数。
c) 我最喜欢的一个-:只需在mongodb或redis中创建一个单独的集合,其中只包含count(这个查询的输出),因为count只有1个数字。这不需要很大的大小,也不需要更好的查询性能(唯一的问题是,有多少这样的查询,因为这将增加新集合的大小)
2条答案
按热度按时间0ejtzxu11#
试试这个,看看它是否能提高性能:
正如我在评论中提到的,由于
AND ((DATE(cx.last_email_open_date) > '2019-11-08'));
,已制作customers
表到INNER JOIN
与customer_extra
table,你可以把它改成INNER JOIN customer_extra AS cx ON c.id = cx.customer_id
和其他人一起LEFT JOIN
.这个
INNER JOIN
将至少获得初始结果,以便仅返回基于指定内容的上次电子邮件打开日期值的任何客户。lb3vh1jj2#
说
COUNT(*)
,不是COUNT(c.id)
移除这些;它们会减慢查询速度,但不会添加任何我能看到的内容:cx.last_email_open_date > '2019-11-08'
INDEX(shop_id, last_email_open_date) -- in this order