当前位置: 首页 > 知识库问答 >
问题:

mysql - 如何优化MySQL大表联合查询中的COUNT(DISTINCT ID)性能?

康弘义
2024-07-26

真心求解! Mysql 两表联查,A表900w, B表1000w, 分页查询经过索引构建已经没什么问题, 但是count(id)的时候非常慢, 怎么优化

SELECT count(distinct A.id)
FROM A INNER JOIN B ON A.id = B.bus_id
WHERE A.trade_type in (0,1,2,4) and B.user_id IN (68305, 61831, 35444, 54923, 66298, 67438, 67440, 35427, 62213, 62900, 64550, 67658, 68103, 35441, 35466, 66801)
and B.bus_type = 2;
现有索引, A表id二级索引, B表有bus_id, user_id, 以及(bus_id, user_id, bus_type)联合索引, 现在分页查询获取A表数据ms没问题, 只有count(distinct A.id)很慢, 几十s, 不知道怎么处理了, 希望大家提点意见

这是explain得到的结果

ID select_type table type possible_key key key_len ref rows extra
1 SIMPLE B index idx_bus_id,idx_user_id,idx_bus_type_user_id idx_bus_type_user_id 14 9962728 Using where; Using index
1 SIMPLE A eq_ref PRIMARY PRIMARY 4 B 1 Using index

共有1个答案

古弘
2024-07-26

要优化MySQL中涉及大表联合查询的COUNT(DISTINCT ID)操作的性能,你可以尝试以下几种方法:

1. 使用近似计数

对于非常大的数据集,精确计数可能非常耗时。如果业务场景允许,可以考虑使用近似计数方法,如MySQL的SQL_CALC_FOUND_ROWS(但注意,这在分页时可能不是最优选择,且对于COUNT(DISTINCT)不直接支持)或者使用第三方解决方案如Redis的HyperLogLog等。

2. 预先计算和缓存

  • 定期计算并存储结果:如果查询条件(如trade_typeuser_id列表)相对稳定,可以考虑定期(如每天或每小时)运行一个后台任务来计算这些COUNT(DISTINCT)值,并将结果存储在数据库的另一个表中或缓存系统(如Redis)中。
  • 增量更新:当数据发生变化时,只更新受影响的计数值。

3. 优化查询和索引

  • 检查并优化索引:确保你的索引是最优的。在你的场景中,你已经有了(bus_id, user_id, bus_type)的联合索引,这通常是一个好的开始。然而,对于COUNT(DISTINCT A.id),如果A.idA表中不是主键或唯一索引,确保它是索引的。
  • 重写查询:尝试不同的查询写法,看看是否可以提高性能。虽然对于COUNT(DISTINCT)来说,重写空间可能有限,但值得一试。

4. 使用物化视图

如果你的MySQL版本支持(MySQL 5.7及以上版本对物化视图的支持有限,主要通过其他方式实现类似功能),可以考虑使用物化视图来存储计算后的COUNT(DISTINCT)值。然而,MySQL的物化视图功能不如一些其他数据库系统那样强大和直接。

5. 分析和调整配置

  • 查询分析:使用EXPLAINEXPLAIN ANALYZE(MySQL 8.0+)来分析查询的执行计划,查看是否有可以优化的地方。
  • 调整MySQL配置:考虑调整MySQL的配置参数,如buffer_pool_sizesort_buffer_size等,这些可以影响查询性能。

6. 分布式数据库或数据库分片

  • 如果数据量继续增长,并且单个数据库实例已无法满足性能需求,考虑使用分布式数据库系统或数据库分片技术。这可以将数据分布在多个数据库实例上,从而提高查询性能。

结论

针对你的具体查询,最直接的改进可能是通过缓存或预先计算来避免实时计算COUNT(DISTINCT A.id)。同时,确保所有相关的列都已被正确索引,并尝试使用EXPLAIN来优化查询计划。如果这些方法仍不能满足性能要求,可能需要考虑更复杂的解决方案,如使用分布式数据库或近似计数方法。

 类似资料:
  • 我有一个需要50秒的查询 security_tasks中的记录=841321 relations中的记录=234254 我能做些什么让它快一点,比如快1秒或2秒 有什么想法吗?

  • 在MySQL数据库中,我遇到了一个问题,当我在执行一个JOIN查询时,发现查询性能显著降低,特别是在两个大表之间进行JOIN操作时。我的两个表分别是orders(订单表,大约有1000万条记录)和customers(客户表,大约有500万条记录),它们通过customer_id字段相关联。我已经为这两个表的customer_id字段建立了索引,但是在执行如下JOIN查询时,耗时仍然较长: 运行环境

  • 本文向大家介绍如何对MySQL联合查询计数?,包括了如何对MySQL联合查询计数?的使用技巧和注意事项,需要的朋友参考一下 要对联合进行计数,即获取UNION结果的计数,请使用以下语法- 为了理解上述语法,让我们创建两个带有一些记录的表。创建表的查询如下- 使用insert命令在表中插入一些记录。查询如下- 使用select语句显示表中的所有记录。查询如下- 以下是输出- 该查询创建第二个表。 使

  • 主要内容:概述,一、关联查询优化,1.左(右)外连接,2.内连接,3.JOIN语句原理,4.JOIN小结,5.Hash Join,二、子查询优化,三、排序优化,四、GROUP BY优化,五、优先考虑覆盖索引,六、使用前缀索引,七、索引下推ICP,八、其他查询优化,1.COUNT(*)与COUNT(具体字段)效率,2.不使用SELECT *,3.LIMIT 1优化,4.多使用commit概述 数据库调优的方式有多种: 建立索引、充分利用到索引、不让索引失效 对SQL语句进行优化 调优如缓冲、线程数

  • 问题内容: 这就是整个查询… 如果… 和… 有明显的理由吗? 正在服用? 扩展说明 问题答案: 您可以始终使用EXPLAIN或EXPLAIN EXTENDED 来查看MySql对查询所做的操作 您也可以用稍微不同的方式编写查询,是否尝试过以下方法? 看看效果如何会很有趣。我希望它会更快,因为目前,我认为MySql将为您拥有的每个节目运行内部查询1(这样一个查询将运行多次。联接应该更有效。) 如果希

  • 问题内容: 一个供您所有MySQL专家使用的技巧:-) 我有以下查询: 订单表= 80,900行 产品表= 125,389行 o.id和p.order_id已建立索引 该查询大约需要6秒钟才能完成-太长了。我正在寻找一种优化它的方法,可能使用临时表或其他类型的联接。恐怕我对这两个概念的理解还很有限。 谁能建议我优化此查询的方法? 问题答案: 首先,我将使用其他样式的语法。 已经有20年的睡眠时间了

  • 本文向大家介绍如何做 MySQL 的性能优化?相关面试题,主要包含被问及如何做 MySQL 的性能优化?时的应答技巧和注意事项,需要的朋友参考一下 为搜索字段创建索引。 避免使用 select *,列出需要查询的字段。 垂直分割分表。 选择正确的存储引擎。

  • 问题内容: 我有一个NewsStories表格,剩下一些相关表格。每个新闻故事可以具有多个图像,类别和地址。因此查询实质上是: 通常每个故事有一些图像和地址,以及1或2个类别。NewsStories表包含大约10,000条文章。 问题在于性能相当慢(大约15-20秒,尽管它的确变化很大,有时甚至低至5秒)。 我想知道是否有更好的方法来组织查询以加快查询速度(我对SQL还是很陌生)。 尤其是,给定故