目录
一 、MySQL优化
1、慢查询
2、慢查询日志分析工具
2.1、mysqldumpslow工具
2.2、pt-query-digest工具
2.3、三大类有问题的SQL
3、通过explain分析SQL执行计划
4、慢查询优化思路
4.1、整体优化思路:
4.2、永远用小结果集驱动大的结果集
4.3、join的实现原理
4.4、join的优化思路
4.5、只取出需要的列,不要用select *
4.6、order by实现及优化思路
4.7、group by实现及优化思路
4.8、distinct的实现及优化思路
4.9、合理设计并利用索引
5、数据库其他优化原则
5.1、总体优化原则
5.2、字段优化原则
5.3、索引优化原则
5.4、SQL类优化原则
5.5、结构类优化原则
6、参考
一 、MySQL优化
1、慢查询
(1)检查慢查询日志是否开启
show variables like 'slow_query_log';
(2)检查慢查询日志路径
show variables like '%slow_query_log%';
(3)开启慢查询日志
set global slow_query_log=on;
(4)慢日志判断标准(默认10秒)
show variables like 'long_query_time';
(5)开启所有语句都记录到慢查询日志(不要轻易打开)
set global log_queries_not_using _indexes=on;
2、慢查询日志分析工具
2.1、mysqldumpslow工具
2.1.1 简介:如果开启了慢查询日志,就会生成大量的数据,然后我们就可以通过对日志分析,生成分析报表,通过报表进行优化。
2.1.2 用法:执行 mysqldumpslow --help查看详细用法。
2.1.3 优缺点:通过安装MySQL附带安装,但该工具统计结果比较少,比如没有cpu、io等信息。
2.2、pt-query-digest工具
2.2.1 简介:
pt-query-digest是用于分析myql慢查询的一个第三方工具,他可以分析biglog、General log、slowlog,也可以通过SHOWPROCESSLIST或通过tcpdump抓取MySQL协议数据来进行分析。可以把分析结果输出到文件中,分析过程是先对查询语句条件进行优化,然后对参数化以后的查询进行分组统计,统计出各查询的执行时间、次数、占比等,可以借助分析结果找出问题进行优化。
2.2.2 安装:
(1)pt-query-digest本质是perl脚本,所以首先安装perl模块
yum install -y perl-CRAN perl-Time-HiRes
(2)官网地址:
https://www.percona.com/downloads/
(3)安装:
wget https://www.percona.com/downloads/percona-toolkit/3.2.0/binary/redhat/7/x86_64/percona-toolkit-3.2.0-1.el7.x86_64.rpmyum localinstall -y percona-toolkit-3.2.0-1.el7.x86_64.rpm
(4)检查是否安装完成
pt-query-digest --help
2.2.3 常用命令详解
(1)查看服务器信息
pt-summary
可以看到服务器相关的具体信息:有系统日期,主机,更新时间,内核,平台,进程数等。
(2)查看磁盘开销使用信息
pt-diskstats
(3)查看MySQL数据库信息
pt-mysql-summary --user=root --password=123456
(4)分析慢查询日志(重点)
pt-query-digest /var/lib/mysql/localhost-slow.log
(5)查找MySQL的从库和同步状态
pt-slave-find --host=localhost --user=root --password=123456
注意:如果以下报错
DBI connect(';host=localhost;mysql_read_default_group=client','root',...) failed: Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory at /usr/bin/pt-slave-find line 2023.
从错误信息可知caching_sha2_password不能加载。
以上报错是由于目前已有的客户端连接软件还不支持MySQL8新增加的加密方式caching_sha2_password,所以我们需要修改用户的加密方式,将其改为老的加密验证方式。
处理方法:
// 进入mysql库use mysql;// 执行以下SQLselect user,plugin from user where user='root';// 修改加密方式为 mysql_native_passwordalter user 'root'@‘localhost' identified with mysql_native_password by '123456';// 刷新flush privileges;
(6)查看MySQL死锁信息
pt-deadlock-logger --run-time=10 --interval=3 --create-dest-table --dest D=test,t=deadlocks u=root,p=123456
(7)从慢查询日志中分析索引使用情况
pt-index-usage --user=root --password=123456 --host=localhost /var/lib/mysql/localhost-slow.log
(8)从慢查询日志中找数据库重复的索引
pt-duplicate-key-checker --host=localhost --user=root --password=123456
(9)查看MySQL表和文件的当前活动IO开销(不要在高峰时用)
pt-ioprofile
(10)查看不同MySQL配置文件的差异(集群用,双方都生效的变量)
pt-config-diff /etc/my.cnf /root/my_master.cnf
(11)pt-find查找MySQL表和执行命令
// 查找数据库里大于1M的表pt-find --user=root --password=123456 --tablesize +1M
(12)查看表和索引大小并排序
pt-find --user=root --password=123456 --printf "%T\t%D.%N\n" | sort -rn
(13)pt-kill杀掉符合标准的MySQL进程
// 显示查询时间大于1秒的查询pt-kill --user=root --password=123456 --busy-time 1 --print// 杀掉查询时间大于1秒的查询pt-kill --user=root --password=123456 --busy-time 1 --kill
(14)查看MySQL授权(集群常用,授权复制)
pt-show-grants --user=root --password=123456pt-show-grants --user=root --password=123456 --separate --revoke
可以看到大量的授权信息,这个命令主要也是用在集群的时候,在从机上需要和主机上进行一模一样的授权,直接可以通过这个命令获取所有的授权,然后复制过去就ok了。
(15)验证数据库复制的完成性(集群常用,主从复制后检验)
pt-table-checksum --user=root --password=123456
这个信息主要查看点是ERRORS和DIFFS的信息,如果不为0就要注意了,检查主从复制的时候是不是出现了问题。
’
2.3、三大类有问题的SQL
- 查询次数多且每次查询占用时间长的SQL:通常为pt-query-digest分析的前几个查询,该工具可以很清楚的看出每个SQL执行的次数及百分比等信息,执行的次数多,占比比较大的SQL。
- IO大的SQL:注意pt-quert-digest分析中的Rows examine项,扫描行数越多,IO越大。
- 未命中索引的SQL:pt-quert-digest分析中的Rows examine和Rows Send的对比,说明该SQL的索引命中率不高
3、通过explain分析SQL执行计划
SQL的执行计划反映了SQL的执行效率,在执行SQL前面加上explain即可。
- id:数字越大越先执行,如果数字一样大,那么就从上往下依次执行,id列为NULL就表示这是一个结果集,不需要使用它来进行查询。
- select_type:
- simple:表示不需要union操作或者不包含子查询的简单select查询,有连接查询时,外层的查询为simple,且只有一个。
- primary:一个需要union操作或者含有子查询的select,位于最外层的查询,select_type即为primary,有且只有一个。
- union:union连接的两个select查询,第一个查询是dervied派生表,除了第一个表外,第二个以后的表select_type都是union。
- union result:包含union的结果集,在union和union all语句中,因为它不需要参与查询,所以id字段为NULL。
- dependent union:与union一样,出现在union和union all语句中,但是这个查询要受到外部查询的影响。
- subquery:除了from字句中包含的子查询外,其他地方出现的子查询都可能是subquery。
- dependent subquery:与dependent union类似,表示这个subquery的查询要受到外部表查询的影响。
- derived:from字句中出现的子查询,也叫派生表,其他数据库中可能叫做内联视图或嵌套select。
- materialization:物化通过将子查询结果作为一个临时表来加快查询执行速度,正常来说是常驻内存,下次查询会再次引用临时表。
- table:显示的查询表名,如果查询使用了别名,那这里显示的是别名,如果不涉及对数据库的操作,那么这显示NULL,如果显示为尖括号括起来的就表示这个是临时表,后面的N就是执行计划的ID,表示结果来自于这个查询产生。如果是尖括号括起来的,与类似,也是一个临时表,表示这个结果来自于union查询的id为M、N的结果集。
- type:
- system:表中只有一行数据或者是空表,且只能用于myisam和memory引擎,如果是Innodb引擎,type列在这个情况通常都是all或者index。
- const:使用唯一索引或者主键,返回记录一定是一行记录的等值where条件时,通常type是const,其他数据库也叫做唯一索引扫描。
- eq_ref:出现在要连接多个表的查询计划中,驱动表循环获取数据,这行数据是第二个表的主键或者唯一索引,作为条件查询只返回一条数据,且必须为not null,唯一索引和主键是多列时,只有所有的列都用作比较时才会出现eq_ref。
- ref:不像eq_ref那样要求连接顺序,也没有主键和唯一索引的要求,只要使用相等条件检索时就可能出现,常见与辅助索引的等值查找或者多列主键、唯一索引中,使用第一个列之外的列作为等值查找也会出现,总之,返回数据不唯一的等值查找就可能出现。
- fulltext:全文索引检索,全文索引的优先级最高,若全文索引和普通索引同时存在时,MySQL不管代价,优先选择使用全文索引。
ref_or_null:与ref类似,只是增加了null值比较,实际用的不多。
union_subquery:用于where中的in形式子查询,子查询返回不重复唯一值。 - index_subquery:用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。
- range:索引范围扫描,常见于使用>,
- index_merge:表示查询使用了两个以上的索引,最后取交集或者并集,常见and、or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取多个索引,性能可能大部分时间都不如range。
- index:索引全表扫描,把索引从头到尾扫一遍,常见于使用索引列就可以处理不需要读取数据文件的查询,可以使用索引排序或者分组查询。
- all:这个就是全表扫描数据文件,然后在server层进行过滤返回符合要求的记录。
type总结:依次性能从好到差:system、const、eq_ref、ref、fulltext、ref_or_null、unique_subquery、index_subquery、range、index_merge、index、all。除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引。一般来说,好的SQL查询至少达到range级别,最好能达到ref。
- possible_keys:查询可能使用到的索引。
- key:查询真正使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
- key_len:用于处理查询的索引长度,如果是单列索引,那就是整个索引长度,如果是多列索引,那么查询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的列不会计算进去。留意下这个列的值,算一下你的多列索引总长度就知道有没有使用到所有的列了。另外,key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。
- ref:如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func。
- rows:这里是执行计划中估算的扫描行数,不是精确值。
- extra:
- no tables used:不带from字句的查询或者from dual查询。
- null:查询的列未被索引覆盖,并且where筛选条件是索引的前导列,意味着用到了索引,但是部分字段未被索引覆盖,必须通过“回表”来实现,不是纯粹地用到了索引,也不是完全没用到索引。
- using index:查询时不需要回表查询,直接通过索引就可以获取查询的数据。
- using where:查询的列未被索引覆盖,where筛选条件非索引的前导列。
- using where using index:查询的列被索引覆盖,并且where筛选条件是索引列之一但是不是索引的前导列,意味着无法直接通过索引来查到符合条件的数据。
- using index condition:与using where类似,查询的列不完全被索引覆盖,where条件中是一个前导列的范围。
- using temporary:表示使用了临时表存储中间结果。临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,uesd_tmp_table、use_tmp_disk_table才能看出来。
- using filesort:MySQL会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。此时MySQL会根据联结类型浏览所有符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息。这种情况下一般也是要考虑使用索引来优化的。
- using intersect:表示使用and的各个索引的条件时,该信息表示是从处理结果获取交集。
- using union:表示使用or连接各个使用索引的条件时,该信息表示从处理结果获取并集。
- using sort_union、using sort_intersection:用and和or查询信息量大时,先查询主键,然后进行排序合并后返回结果集。
- firstmatch(tb_name):5.6.x开始引入的优化子查询的新特性之一,常见于where字句含有in()类型的子查询。如果内表的数据量比较大,就可能出现。
- loosescan(m..,n):5.6.x之后引入的优化子查询的新特性之一,在in()类型的子查询中,子查询返回的可能有重复记录时,就可能出现。
- filtered:使用explain extended时会出现这个列,5.7之后的版本默认就有这个字段,不需要使用explain extended了。这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数。
4、慢查询优化思路
4.1、整体优化思路:
- 优化更需要优化的SQL;
- 定位优化对象的性能瓶颈;
- 明确的优化目标;
- 从explain执行计划入手;
- join永远用小结果集驱动大的结果集;
- 尽可能在索引中完成排序;
- 只取出自己需要的列,不用select *;
- 仅使用最有效的过滤条件;
- 尽可能避免复杂的join和子查询;
- 小心使用order by,group by(需要排序),distinct(需要分组);
- 合理设计并利用索引;
4.2、永远用小结果集驱动大的结果集(join操作表小于百万级别)
4.2.1、驱动表的定义
当进行多表连接查询时, [驱动表] 的定义为:
- 指定了联接条件时,满足查询条件的记录行数少的表为[驱动表];
- 未指定联接条件时,行数少的表为[驱动表];
4.2.2、MySQL关联查询的概念
MySQL 表关联的算法是 Nest Loop Join,是通过驱动表的结果集作为循环基础数据,然后一条一条地通过该结果集中的数据作为过滤条件到下一个表中查询数据,最后合并结果。
4.2.3、left join,right join,inner join的区别
- left join
select * from t2 left join t3 on t2.id =t3.id and t3.id in(1,2,3) order by t2.id desc;
- right join
select * from t2 right join t3 on t2.id =t3.id and t3.id in(1,2,3);
- inner join
select * from t2 inner join t3 on t2.id =t3.id and t3.id in(1,2,3);
4.3、join的实现原理
只支持一种算法Nest-Loop Join(嵌套循环连接),有三个变种:
- Simple Nest-Loop Join(简单嵌套循环)
说明:
- 左边为驱动表,右边为被驱动表
- 将驱动表/外部表的结果集作为循环基础数据,然后循环从该结果集每次一条获取数据作为被驱动表的过滤条件查询数据,然后合并结果。
- 如果有多表join,则将驱动表的结果集作为循环数据,取到每行再到联接的被驱动表中循环匹配,获取结果集返回给客户端。
- Index Nest-Loop Join(索引嵌套循环)
说明:与Simple Nest-Loop Join不用在于,先查询驱动表的索引的结果集作为循环基础数据,然后循环从该结果集每次一条获取数据作为被驱动表的过滤条件查询数据,然后合并结果。
- Block Nest-Loop Join(块嵌套循环)
说明:
- 将外层循环的行/结果存入join buffer,内层循环的每一行与整个buffer中的记录做比较,从而减少循环的次数。
- 通过变量join_buffer_size来决定buffer大小,默认256K。
- Block Nested-Loop Join(3表)
4.4、join的优化思路
- 尽可能减少join语句中的Nest-Loop的循环次数;
- 优先优化 Nest-Loop的内层循环;
- 保证join语句中被驱动表上join条件字段已经被索引;
- 调整join buffer大小;
- 复杂的多个join语句拆分成多个较为简单的query单表分布执行(不超过三个表);
4.5、只取出需要的列,不要用select *
- 如果取出的列过多,则传输给客户端的数据量必然很大,浪费带宽;
- 若在排序的时候输出过多的列,则会浪费内存(Using filesort);
- 若在排序的时候输出过多的列,还有可能改变执行计划;
4.6、order by实现及优化思路
- order by排序可利用索引进行优化,order by字句中只要是索引的前导列都可以使索引生效,可以直接在索引中排序,不需要再额外的内存或者文件中排序。
- 不能利用索引避免额外排序的情况,例如:排序字段中有多个索引,排序顺序和索引键顺序不一致(非前导列).
4.6.1、order by常规排序算法
(1)简介:
MySQL对于不能利用索引避免排序的SQL,数据库不得不自己实现排序功能以满足用户需求,此时SQL的执行计划中会出现“using filesort”,这里需要注意的是filesort并不意味着就是文件排序,其实也有可能是内存排序,这个主要由sort_buffer_size参数与结果集大小确定。MySQL内部实现排序主要由3种方式,常规排序、优化排序和优先队列排序,主要涉及3种排序算法:快速排序、归并排序和堆排序。
涉及排序相关参数:sort_buffer_size、read_rnd_buffer_size
(2)步骤:
- 从表t1中获取满足where条件的记录
- 对于每条记录,将记录的主键+排序键取出放入sort buffer
- 如果sort buffer可以存放所有满足条件的字段时,则进行排序;否则sort buffer满后,进行排序并固话到临时表中。(排序算法采用的是快速排序算法)
- 若排序中产生了临时文件,需要利用归并排序算法,保证临时文件中记录是有序的
- 循环执行以上过程,直到所有满足条件的记录全部参与排序
- 扫描排好序的字段,并利用id去捞取select需要返回的字段
- 将获取的结果集返回给客户端
4.6.2、order by优化排序算法
常规排序方式除了排序本身,还需要额外零次IO。优化的排序方式相对于常规排序,减少了第二次IO。
主要区别在于,放入sort buffer不是(id、col2),而是(id、col2、col3)。由于sort buffer中包含了查询需要的所有字段,因此排序完成后可以直接返回,无需第二次捞数据。这种方式的代价在于,同样大小的sort buffer能存放的(id、col2、col3)数目要小于(id、col2),如果sort buffer不够大,可以导致需要写临时文件,造成额外IO。
涉及相关排序参数:max_length_for_sort_size
4.6.3、order by优先队列排序算法
5.6及之后的版本针对order by limit M,N 语句,在空间层面做了优化,加入了一种新的排序方式——优先队列,这种方式采用堆排序实现。堆排序算法特征正好可以解limit M,N 这类排序问题,虽然仍然需要所有元素参与排序,但是只需要M+N个元祖的sort buffer空间即可,对于M,N 很小的场景,基本不会因为sort buffer不够而导致需要临时文件进行归并排序的问题。对于升序,采用大顶堆,最终堆中的元素组成了最小的N个元素,对于降序,采用小顶堆,最终堆中元素组成了最大的N个元素。
4.6.4、order by 排序分页的数据不一致问题
- MySQL5.6发现分页出现了重复值
- MySQL8查询正常
- 原因分析及解决方案
针对limit M,N 的语句采用优先队列,而优先队列采用堆实现,而堆排序是非稳定的(对于相同的key值,无法保证排序后与排序前位置一致),所以导致了分页重复的现象。为了避免这个问题,我们可以在排序中加上唯一值,比如主键id,这样由于id是唯一的,确保参与排序的key值不同。
4.7、group by实现及优化思路
- group by本质上也同样需要进行排序优化操作(MySQL8优化了,默认不排序),而且与order by相比,group by主要只是多了排序之后的分组操作。如果在分组的时候还使用了其他的一些聚合函数,那么还需要进行聚合函数的计算,所以在group by的实现过程中,与order by一样也可以利用索引。
- group by三种实现类型
- Loose Index Scan(松散索引扫描)
说明:先根据group by后面的字段进行分组,分组不需要读取所有索引的key。例如index(key1,key2,key3),在group by key1,key2的时候,此时只要读取索引中key1,key2,然后再根据where条件进行筛选。
- Tight Index Scan(紧凑索引扫描)
说明:紧凑索引扫描需要在扫描索引的时候,读取所有满足条件的索引键,然后再根据读取的数据来完成group by操作得到相应的结果。区别就是紧凑索引扫描是先执行where操作,再进行分组,松散索引扫描则相反。
- Using temporary 临时表 (非索引扫描)
说明:MySQL在进行group by操作的时候当mysql query optimizer无法找到合适的索引可以利用的时候,就不得不先读取需要的数据,然后通过临时表来完成group by操作。
4.8、distinct的实现及优化思路
distinct实际上和group by的操作非常相似,在group by之后的每组中只取出一条记录而已。所以,distinct的实现和group by的实现也基本差不多,同样可以通过松散索引扫描或者紧凑索引扫描来实现,当然,在无法仅仅使用索引既能完成distinct的时候,MySQL只能通过临时表来完成。但是,和group by有一点差别是,distinct并不需要进行排序。
4.9、合理设计并利用索引
索引类别:
- B-tree索引(MySQL中使用最频繁的索引类型)
- Hash索引(检索效率远高于B-tree索引,可以一次定位)
- Fulltext索引(目前仅char、varchar、text这三种类型)
- R-tree索引(比较少见,主要用于空间数据检索)
4.9.1、B-tree索引
4.9.2、B+tree索引(InnoDB引擎)
与B-tree索引区别
- 非叶子节点只存储键值信息;
- 所有叶子节点双向指针;
- 所有数据在叶子节点;
B+tree索引又分为聚簇索引和辅助索引
两者区别:辅助索引所有叶子节点并不包含行记录的全部数据,而是相应行记录的聚簇索引值(主键),根据主键值再到聚簇索引找到数据(两次索引)
4.9.3、如果判断是否需要创建索引
- 较频繁的作为查询条件的字段应该创建索引;
- 唯一性太差的字段不适合单独创建索引,可以尝试复合索引;
- 更新非常频繁的字段不适合创建索引;
- 不会出现在where字句中的字段不该创建索引;
4.9.4、索引失效和优化
- 复合索引尽量全匹配;
- 最佳左前缀法则(带头字段不能少,中间字段不能断);
- 不要在索引上做任何操作(计算、函数、自动/手动类型转换),不然会导致索引失效而转向全表扫描;
- MySQL存储引擎不能继续使用索引中范围条件(between、、in等)右边的列;
- 尽量使用覆盖索引(只查询索引的列(索引列和查询列一致)),减少select *;
- 索引字段上使用 !=或者<>判断时,会导致索引失效而转向全表扫描;
- 索引字段上使用 is null或者is not null判断时,会导致索引失效而转向全表扫描(版本8未必失效);
- 索引字段上使用 like 以通配符开头(“%字符串”)时,会导致索引失效而转向全表扫描;
- 索引字段上使用字符串,但查询是不加单引号,会导致索引失效而转向全表扫描;
- 索引字段上使用 or 时,会导致索引失效而转向全表扫描;
5、数据库其他优化原则
5.1、总体优化原则
- 不在数据库做运算,运算务必移至业务层;
- 库命名简洁明确(长度不超过30个字符);
- 控制字段数量(字段少而精,字段数建议在20以内);
- 平衡范式与冗余(效率优先,往往牺牲范式);
- 拒绝3B:拒绝大SQL(big SQL),拒绝大事务(big transaction),拒绝大批量(big batch);
5.2、字段优化原则
- 用好数值类型(用合适的字段类型节约空间);
- 字符转化为数字(能转化的最好转化,节约空间,提高查询性能);
- 避免使用null字段(null字段很难查询优化,null字段的索引需要额外空间,null字段的复合索引无效);
- 少用text类型(尽量使用varchar代替text字段);
5.3、索引优化原则
- 合理使用索引(改善查询,减慢更新,索引一定不是越多越好);
- 字符字段建前缀索引;
- 不在索引做运算;
- innodb引擎主键推荐使用自增主键(主键建立聚簇索引,主键不应该被修改,字符串不应该做主键),不用外键;
5.4、SQL类优化原则
- SQL语句尽可能简单(一条SQL只能在一个cpu运算,大语句拆小语句,减少锁时间,一条大SQL可以堵死整个库);
- 简单的事务;
- 避免使用trig/func(不用触发器,函数。用客户端程序取而代之);
- 不用select *(消耗cpu,io,内存,带宽);
- or改写为in(字段没有索引下性能差异大);
- or改写union(索引无效变有效);
- 使用union all替代union(union有去重开销);
- 少用连接join(超过3个,一到移到业务代码里);
- 分页limit优化(偏移量越大,执行越慢);
5.5、结构类优化原则
- 表范式化原则:范式化是指数据库设计的规范吗,目前范式化一般是指设计到第三范式,也就是要求数据表中不存在非关键字段对任意候选关键字段的传递函数依赖,则符合第三范式。;
- 反范式化原则:反范式化是指为了查询效率的考虑,把原本符合第三范式的表“适当”的添加冗余,以达到优化查询效率的目的,反范式化是一种以空间来换时间的操作;
- 垂直拆分原则:
- 不常用的字段单独存放到一个表中
- 大字段单独放到一个表中
- 经常一起使用的字段放到一起
- 水平拆分原则:
- 表的水平拆分是为了解决单表数据量过大的问题
- 尽量加了完美的索引,查询效率低,写入效率也相应的降低
- 通常对id进行hash运算,如果要拆分为5个表则使用mod(id,5)取出0-4个值
6、参考
MySQL官网:https://www.mysql.com/