Mysql加入性能MongoDB,Cassandra
我有一个连接查询,需要花费很多时间来处理Mysql加入性能MongoDB,Cassandra,mysql,database,mongodb,performance,cassandra,Mysql,Database,Mongodb,Performance,Cassandra,我有一个连接查询,需要花费很多时间来处理 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` =
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万条记录一天可能会变成10亿条记录
我正在寻找能够提高性能的解决方案。
我已经考虑过了
a) 横向可扩展性:将mysql表分为不同的部分,并独立查询计数
b) 使用复合索引
c) 我最喜欢的一个-:只需在mongodb或redis中创建一个单独的集合,其中只包含计数(此查询的输出),因为计数只有1个数字。这不需要很大的大小,也不需要更好的查询性能(唯一的问题是,有多少这样的查询,因为这会增加新集合的大小)试试这个,看看它是否能提高性能:
SELECT
COUNT(c.id)
FROM `customers` AS `c`
INNER JOIN `customer_extra` AS `cx` ON `c`.`id` = `cx`.`customer_id`
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`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'));
INDEX(shop_id, last_email_open_date) -- in this order
正如我在评论中提到的,由于条件和((日期(cx.last_email_open_DATE)>“2019-11-08”)
,已将客户
表设置为内部联接
与客户_extra
表一起,您可以将其更改为内部联接客户_extra,作为c.id=cx.customer _id
上的cx,然后使用其他左联接
内部联接将至少获得初始结果,根据指定的日期值,仅返回上次使用电子邮件打开日期值的任何客户。尝试此操作,看看是否能提高性能:
SELECT
COUNT(c.id)
FROM `customers` AS `c`
INNER JOIN `customer_extra` AS `cx` ON `c`.`id` = `cx`.`customer_id`
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`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'));
INDEX(shop_id, last_email_open_date) -- in this order
正如我在评论中提到的,由于条件和((日期(cx.last_email_open_DATE)>“2019-11-08”)
,已将客户
表设置为内部联接
与客户_extra
表一起,您可以将其更改为内部联接客户_extra,作为c.id=cx.customer _id
上的cx,然后使用其他左联接
内部连接将至少获得初始结果,根据指定的内容,仅返回具有上次电子邮件打开日期值的任何客户。
- 说
COUNT(*)
,而不是COUNT(c.id)
- 移除这些;它们会降低查询速度,但不会添加任何我能看到的内容:
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`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`
DATE(…)
使该测试不“可搜索”。这适用于日期
或日期时间
;这要快得多:
cx.last_email_open_date > '2019-11-08'
- 考虑是否应该是
=
而不是
- 需要
店铺id
上的索引。(请提供显示创建表)
- 当
JOIN
同样有效时,不要使用LEFT JOIN
- 如果
customer\u extra
是应该在customer
中的列,现在是将它们移入的时候了。这将使您可以使用此复合索引获得更高的性能:
SELECT
COUNT(c.id)
FROM `customers` AS `c`
INNER JOIN `customer_extra` AS `cx` ON `c`.`id` = `cx`.`customer_id`
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`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'));
INDEX(shop_id, last_email_open_date) -- in this order
有了这些更改,MySQL中的10亿行可能不会成为问题。如果是,我还可以建议更多的修复方法。
- 说
COUNT(*)
,而不是COUNT(c.id)
- 移除这些;它们会降低查询速度,但不会添加任何我能看到的内容:
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`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`
DATE(…)
使该测试不“可搜索”。这适用于日期
或日期时间
;这要快得多:
cx.last_email_open_date > '2019-11-08'
- 考虑是否应该是
=
而不是
- 需要
店铺id
上的索引。(请提供显示创建表)
- 当
JOIN
同样有效时,不要使用LEFT JOIN
- 如果
customer\u extra
是应该在customer
中的列,现在是将它们移入的时候了。这将使您可以使用此复合索引获得更高的性能:
SELECT
COUNT(c.id)
FROM `customers` AS `c`
INNER JOIN `customer_extra` AS `cx` ON `c`.`id` = `cx`.`customer_id`
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`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'));
INDEX(shop_id, last_email_open_date) -- in this order
有了这些更改,MySQL中的10亿行可能不会成为问题。如果是的话,我还可以建议更多的修复方法。首先,因为您需要和((日期(cx.last_email_open_DATE)>“2019-11-08”)代码>,已将客户
表与客户_extra
表进行内部连接。所以,您可能想将它稍微更改为,从客户作为c内部连接客户作为cx的额外连接代码>然后仅左连接
其他表?Thx。回答这个问题。我会接受itOk,但它会提高性能吗?如果是,改进了多少?首先,因为你做了和((日期(cx.last_email_open_DATE)>'2019-11-08')代码>,已将客户
表与客户_extra
表进行内部连接。所以,您可能想将它稍微更改为,从客户作为c内部连接客户作为cx的额外连接代码>然后仅左连接
其他表?Thx。回答这个问题。我会接受itOk,但它会提高性能吗?如果是,改善了多少?