mysql分表真得能提升查询性能吗

mysql分表真得能提升查询性能吗,第1张

首先将存储引擎限定在innodb

如果将不同的表分到多个库多个机器上,那一定是能提升性能的,毕竟你花钱买机器了,总的可用CPU和内存高了。这种情况不必考虑。

如果所有分表都在同库同机器上,每个表的查询都共用CPU和内存,性能是怎么提升的?

例如这条查询 select * from user_feeds where uid = ? ,且uid字段上有二级索引,查询步骤为:

通过以上步骤可以看出,查询的主要成本为: 确定索引扫描范围的IO次数(最大为4)、遍历扫描范围内索引数据的CPU占用(与扫描范围内记录数成正比)、回表IO次数(与扫描范围内记录数成正比,且受聚簇索引B+树层数影响) 。所以查询的成本主要取决于uid=X对应的记录数量和索引B+树的层数。

来看一下分表后的查询成本:

可见分表后主要的差别在于确定索引扫描范围的IO次数和回表IO次数,即分表后B+树的层数变化,变化范围为0到3。对于不需要回表的查询,差别在于用到的索引B+树层数变化导致的确定扫描范围的IO次数变化;对于需要回表的查询,除了确定扫描范围的IO次数变化,还有回表IO次数变化(回表IO次数变化=记录数X聚簇索引B+树层数变化)。

以上是有二级索引的情况,如果没有索引,需要全表扫描时,扫描整个聚簇索引的成本: 加载数据页到内存的IO次数(聚簇索引的页面数)、扫描记录的CPU占用(整个聚簇索引的记录数量) 。分表以后所有表总的记录数量不变,页面数量也可以认为不变。所以全表扫描的查询性能分表与不分表也不会有什么差别。

垂直分表,表记录数不会改变,每条记录数据占用空间会变小,从而导致单表聚簇索引每个数据页可以存储的记录变多,聚簇索引的数据页数量变少,原来uid=X的记录可能分布在N个数据页上,分表后uid=X的记录分布在的数据页数量<=N。也就是减少回表IO的次数。

但是,这种情况只限于合理的垂直分表,也就是select的列可以落在同一张表中。

索引列:uid、created_at

单条记录大小 uid4字节、created_at4字节、主键post_id8字节,页号6字节 共22字节

单页可以存放的记录数 16kb(16384)/22 = 744,去除掉一些其他信息(header、槽信息),再去除一些碎片(删除造成的、没填满造成的),姑且认为每页存放500条记录

如果总的记录条数为5000w,那么需要的叶子节点数量为 5000w/500 = 10w,B+树需要两层(500X500 = 25w)

索引叶子节点占用空间大小为 10wX16kb = 1.6GB

索引目录节点占用空间大小为 500X16kb = 8M

单条记录大小 24

单页可以存放的记录数 682

与理论估算相近

索引空间大小19.38GB,生产环境二级索引数量16个,平均每个索引空间大小约1.1GB,比理论估算还小一些。

1、除非迫不得已,不建议使用子查询,因为在几乎所有的sql语言中子查询都是效率很低的,并且mysql中的子查询在某些旧版本下面还有不少缺陷。

2、直接连接查询,使用的是笛卡尔积的查询模式。就是把X表中的每一行分别与Y表中的每一行组合一次,10W数据表X与30W数据表Y的笛卡尔积将会产生300W条数据。

3、X,Y直连、join、left join、right join、inner jion都属于直接连接查询,只不过在查询出的结果集中的数据选取方式有区别而已(有的时候也会因为这个区别而产生微量的效率不同)。

4、在你上面的两条语句中,只能用语句1。因为语句1使用了直连,笛卡尔积导致的300W的数据量的主键对等查询的速度上还是说得过去的。而语句2中使用了两个子查询,然后以两个子查询的结果集再做笛卡尔积,然后再在300W数据中做主键对等匹配出结果集,且查询出的结果只能是两个表各自的id,不是你想要的结果,并且你的on语句是错误的,会导致不可预知的结果。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5907640.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-07
下一篇 2023-03-07

发表评论

登录后才能评论

评论列表(0条)

保存