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,但它会提高性能吗?如果是,改善了多少?