【问题标题】:Mysql Join performance MongoDB, CassandraMysql 加入性能 MongoDB、Cassandra
【发布时间】:2020-07-23 19:15:33
【问题描述】:

我有一个连接查询需要很长时间来处理。

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')); 

这主要是因为“客户”表有 200 万条记录。

我可以继续进行索引等。但是,更大的一点是,这 250 万条记录可能在 1 天变成十亿条记录。

我正在寻找可以提高性能的解决方案。 我已经考虑过了

a) 水平可扩展性。 -:将mysql表分布到不同的section,独立查询count。

b) 使用复合索引。

c)我最喜欢的一个 - :只需在 mongodb 或 redis 中创建一个单独的集合,它只包含计数(此查询的输出)因为,计数只是 1 个数字。这不需要很大的大小,也就是更好的查询性能(唯一的问题是,有多少这样的查询,因为这会增加新集合的大小)

【问题讨论】:

  • 首先,既然你做了AND ((DATE(cx.last_email_open_date) > '2019-11-08'));,那已经把customers表变成INNER JOINcustomer_extra表。所以也许你想把它改成FROM customers AS c INNER JOIN customer_extra AS cx ON ... ,然后只有LEFT JOIN其他表?
  • 谢谢。将此作为答案。我会接受的
  • 好的,但它会提高性能吗?如果有,改善了多少?

标签: mysql database mongodb performance cassandra


【解决方案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'));

正如我在评论中提到的,由于条件AND ((DATE(cx.last_email_open_date) > '2019-11-08'));,已经将customers 表与customer_extra 表一起制作为INNER JOIN,您可以将其更改为INNER JOIN customer_extra AS cx ON c.id = cx.customer_id 并与其他LEFT JOIN 一起使用.

INNER JOIN 至少会得到初始结果,根据指定的内容仅返回具有 last_email_open_date 值的任何客户。

【讨论】:

    【解决方案2】:
    • 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(...) 使该测试不是“可分析的”。这适用于DATEDATETIME;这要快得多:

      cx.last_email_open_date > '2019-11-08'
      
    • 考虑是否应该使用>= 而不是>

    • 需要shop_id 的索引。 (请提供SHOW CREATE TABLE。)
    • 不要使用LEFT JOIN,因为JOIN 也同样有效。
    • 如果 customer_extra 是本应在 customer 中的列,现在是时候将它们移入。这将使您可以使用此复合索引来获得更高的性能:

      INDEX(shop_id, last_email_open_date)   -- in this order
      

    通过这些更改,MySQL 中的十亿行可能不会成为问题。如果是,我还可以提出更多修复建议。

    【讨论】:

      猜你喜欢
      • 2012-01-28
      • 2017-06-03
      • 2017-09-13
      • 2016-07-12
      • 2012-06-12
      • 2012-01-14
      • 2011-08-22
      • 1970-01-01
      • 2018-01-12
      相关资源
      最近更新 更多