MySQL 对于千万级的大表要怎么优化?

MySQL 对于千万级的大表要怎么优化?

作者:zhuqz

链接:https://www.zhihu.com/question/19719997/answer/81930332

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

很多人第一反应是各种切分;我给的顺序是:
第一优化你的sql和索引;

第二加缓存,memcached,redis;

第三以上都做了后,还是慢,就做主从复制或主主复制,读写分离,可以在应用层做,效率高,也可以用三方工具,第三方工具推荐360的atlas,其它的要么效率不高,要么没人维护;

第四如果以上都做了还是慢,不要想着去做切分,mysql自带分区表,先试试这个,对你的应用是透明的,无需更改代码,但是sql语句是需要针对分区表做优化的,sql条件中要带上分区条件的列,从而使查询定位到少量的分区上,否则就会扫描全部分区,另外分区表还有一些坑,在这里就不多说了;

第五如果以上都做了,那就先做垂直拆分,其实就是根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统;

第六才是水平切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要选择一个合理的sharding key,为了有好的查询效率,表结构也要改动,做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表;

mysql数据库一般都是按照这个步骤去演化的,成本也是由低到高;

有人也许要说第一步优化sql和索引这还用说吗?的确,大家都知道,但是很多情况下,这一步做的并不到位,甚至有的只做了根据sql去建索引,根本没对sql优化(中枪了没?),除了最简单的增删改查外,想实现一个查询,可以写出很多种查询语句,不同的语句,根据你选择的引擎、表中数据的分布情况、索引情况、数据库优化策略、查询中的锁策略等因素,最终查询的效率相差很大;优化要从整体去考虑,有时你优化一条语句后,其它查询反而效率被降低了,所以要取一个平衡点;即使精通mysql的话,除了纯技术面优化,还要根据业务面去优化sql语句,这样才能达到最优效果;你敢说你的sql和索引已经是最优了吗?

再说一下不同引擎的优化,myisam读的效果好,写的效率差,这和它数据存储格式,索引的指针和锁的策略有关的,它的数据是顺序存储的(innodb数据存储方式是聚簇索引),他的索引btree上的节点是一个指向数据物理位置的指针,所以查找起来很快,(innodb索引节点存的则是数据的主键,所以需要根据主键二次查找);myisam锁是表锁,只有读读之间是并发的,写写之间和读写之间(读和插入之间是可以并发的,去设置concurrent_insert参数,定期执行表优化操作,更新操作就没有办法了)是串行的,所以写起来慢,并且默认的写优先级比读优先级高,高到写操作来了后,可以马上插入到读操作前面去,如果批量写,会导致读请求饿死,所以要设置读写优先级或设置多少写操作后执行读操作的策略;myisam不要使用查询时间太长的sql,如果策略使用不当,也会导致写饿死,所以尽量去拆分查询效率低的sql,

innodb一般都是行锁,这个一般指的是sql用到索引的时候,行锁是加在索引上的,不是加在数据记录上的,如果sql没有用到索引,仍然会锁定表,mysql的读写之间是可以并发的,普通的select是不需要锁的,当查询的记录遇到锁时,用的是一致性的非锁定快照读,也就是根据数据库隔离级别策略,会去读被锁定行的快照,其它更新或加锁读语句用的是当前读,读取原始行;因为普通读与写不冲突,所以innodb不会出现读写饿死的情况,又因为在使用索引的时候用的是行锁,锁的粒度小,竞争相同锁的情况就少,就增加了并发处理,所以并发读写的效率还是很优秀的,问题在于索引查询后的根据主键的二次查找导致效率低;

ps:很奇怪,为什innodb的索引叶子节点存的是主键而不是像mysism一样存数据的物理地址指针吗?如果存的是物理地址指针不就不需要二次查找了吗,这也是我开始的疑惑,根据mysism和innodb数据存储方式的差异去想,你就会明白了,我就不费口舌了!

所以innodb为了避免二次查找可以使用索引覆盖技术,无法使用索引覆盖的,再延伸一下就是基于索引覆盖实现延迟关联;不知道什么是索引覆盖的,建议你无论如何都要弄清楚它是怎么回事!

尽你所能去优化你的sql吧!说它成本低,却又是一项费时费力的活,需要在技术与业务都熟悉的情况下,用心去优化才能做到最优,优化后的效果也是立竿见影的!

 
先读写分离、再垂直拆分、再水平拆分!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/113572.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • linux修改用户权限与所属组_linux修改用户组的权限

    linux修改用户权限与所属组_linux修改用户组的权限如何在linux下修改组权限chmodg+rpath/file加读权限当前目录chmod-Rg+rpath/file加读权限当前目录以及子目录g-r减读权限g+w加写权限g-wg+x加执行权限g-x经常会用到的命令,记一下。1.chgrp修改文件所属组#简单使用,将文本test.txt所属组改为gourp1chgrpgourp1test.txt2.chown修改文件拥有…

  • Oracle基础–PL/SQL编程基本语法[通俗易懂]

    Oracle基础–PL/SQL编程基本语法[通俗易懂]一、概念什么是PL/SQL?1.PL/SQL(ProcedureLanguage/SQL)2.PLSQL是Oracle对sql语言的过程化扩展(类似于Basic)3.指在SQL命令语言中增加了过程处理语句(如分支、循环等),使SQL语言具有过程处理能力。二、程序结构通过plsqlDeveloper工具的TestWindow创建程序模版。1.PL/SQL可以分为三个部分:声明部分、可执行部分、异常处理部分。声明部分:此部分是以关键字DECLARE开…

    2022年10月11日
  • ESP32开发之旅——RC522模块的使用

    ESP32开发之旅——RC522模块的使用ESP32开发之旅——RC522模块的使用前言在本文中,您将学会如何使用ESP32连接RFID模块RC522,本文提供了简单的示例供学习参考。需要注意的是,本文中的ESP32是使用MicroPython进行开发的,(同时ESP8266也可按照本文进行开发)。本文中出现的代码是从GitHub开源库中搬运而来,GitHub链接已放在文尾。RFID-RC522模块的简单介绍​ 射频识别RFID(RadioFrequencyIdentification)是一种无线数据传输系统,用于在标签和读取

  • python简单代码_gdal python

    python简单代码_gdal python目标:实现GBDT+LR模型代码,并比较和各种RF/XGBoost+LR模型的效果,发现GBDT+LR真心好用啊。内容:构造GBDT+LR步骤训练阶段:1、获取特性信息2、训练GBDT分类器3、遍历GBDT树的叶子节点,拼接成一个常常的一维向量4、训练OneHot编码器5、训练LR模型预测阶段:1、把带预测的特征输入到GBDT2、获得叶子节点,拼接成一个常常的一维向量3、获得OneHot向量4、LR预测结果这里发现了上篇文章的一个错误:就是GBDT树的叶子节点,输

    2022年10月10日
  • docker容器和主机同网段_docker桥接模式下外网访问

    docker容器和主机同网段_docker桥接模式下外网访问首先我们需要了解的是:每个docker容器都是隔离的,所以它们之间是相互不同的!那么我们开始操作起来,让他们之间可以相互ping通网络。。。一、拉取镜像创建容器1.在这之前首先关闭防火墙;如果显示runinng则执行:sudosystemctlstopfirewalld2.在https://hub.docker.com里拉取镜像busybox(注:busybox相当于小型的c…

  • 解决:java.lang.UnsupportedClassVersionError「建议收藏」

    解决:java.lang.UnsupportedClassVersionError「建议收藏」问题: java.lang.UnsupportedClassVersionError: xxxxx Unsupported major.minor version 52.0启动Tomcat时出现这种错误。造成这种错误的原因是你的Tomcat运行的JDK版本与支持application运行的JDK版本不一致导致的。解决方法: 1、Window—&gt…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号