🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 分析SQL查询慢的方法 1. 记录慢查询日志 分析查询日志,不要直接打开慢查询日志进行分析,这样比较浪费 时间和精力,可以使用pt- query- digest工具进行分析 2. 使用 show profile `set profiling=1`;开启,服务器上执行的所有语句会检测消耗的时 间,存到临时表中 ``` set profiling=1; //开启 profile show profiles show profile for query临时表ID ``` demo ``` mysql > set profiling=1;s mysql > select from a; mysql> show profiles; ``` ![](images/0404627D-CDE1-4337-AAD0-31AD87C32106.jpg) 3. 使用 show status `show status`会返回一些计数器, `show global status`查看服务器级别的所有计数有时根据这些计数,可以猜测出哪些操作代价较高或者消耗时间多 4. 使用 show processlist 观察是否有大量线程处于不正常 5. 使用 explain 分析单条SQL语句 `mysql> explain select * from fq_order\G;` ## 优化查询过程中的数据访问 - 访问数据太多导致查询性能下降 - 确定应用程序是否在检索大量超过需要的数据,可能是太多行或列 - 确认 MYSQL服务器是否在分析大量不必要的数据行 - 查询不需要的记录,使用 limit解决 - 多表关联返回全部列,指定Aid,A.name,Bage - 总是取出全部列, `SELECT*`会让优化器无法完成索引覆盖扫描的优化 - 重复查询相同的数据,可以缓存数据,下次直接读取缓存 ## 是否在扫描额外的记录 使用 explain来进行分析,如果发现查询需要扫描大量的数据但只返回少数的行,可以通过如下技巧去优化: 使用索引覆盖扫描,把所有用的列都放到索引中,这样存储引擎不需要回表获取对应行就可以返回结果 ## 一个复杂查询好与多个简单查询 - MysαL内部每秒能扫描内存中上百万行数据,相比之下,响应数据给客户端就要慢得多 - 使用尽可能少的查询是好的,但是有时将一个大的查询分解为多个小的查询是很有必要 ## 切分查询 将一个大的查询分为多个小的相同的查询一次性删除1000万的数据要比一次删除1万,暂停一会的方案更加损耗服务器开销 ## 分解关联查询 - 可以将一条关联语句分解成多条SQL来执行 - 让缓存的效率更高 - 执行单个查询可以减少锁的竞争 - 在应用层做关联可以更容易对数据库进行拆分 - 查询效率会有大幅提升 - 较少冗余记录的查询 ## 优化 count()查询 - `count(*`)中的`*`会忽略所有的列,直接统计所有列数,因此不要使用 count(列名) - MYISAM中,没有任何 WHERE条件的` count(*)`非常快,当有 WHERE条件, MYISAM的 count统计不一定比其他表引擎快 - 可以使用 explain查询近似值,用近似值替代 count() - 增加汇总表 - 使用缓存 ## 优化关联查询 - 确定ON或者 USING子句的列上有索引 - 确保 GROUP BY和 ORDER BY中只有一个表中的列,这样 MYSQL才有可能使用索引 ## 优化子查询 尽可能使用关联查询来替代 ## 优化 GROUP BY和 DISTINCT - 这两种查询均可使用索引来优化,是最有效的优化方法 - 关联查询中,使用标识列进行分组的效率会更高 - 如果不需要 ORDER BY,进行 GROUP BY时使用 ORDER BY NULL, MYSQL不会再进行文件排序 - WITH ROLLUP超级聚合,可以挪到应用程序处理 > 分类聚合后的结果进行汇总 [参考用法简书 ](https://www.jianshu.com/p/5d2f700b0a31) ## 优化UNON查询 UNION ALL的效率高于 UNION ## 分区表的原理 对用户而言,分区表是一个独立的逻辑表,但是底层 MYSQL将其分成了多个物理子表,这对用户来说是透明的,每一个分区表都会使用一个独立的表文件 . 创建表时使用 partition by子句定义每个分区存放的数据,执行查询时,优化器会根据分区定义过滤那些没有我们需要数据的分区,这样查询只需要查询所需数据在的分区即可 分区的主要目的是将数据按照一个较粗的粒度分在不同的表中,这样可以将相关的数据存放在一起,而且如果想一次性删除整个分区的数据也很方便 ### 适用场景 1. 表非常大,无法全部存在内存,或者只在表的最后有热点数据,其他都是历史数据 2. 分区表的数据更易维护,可以对独立的分区进行独立的操作 3. 分区表的数据可以分布在不同的机器上,从而高效使用资源 4. 可以使用分区表来避免某些特殊的瓶颈 5. 可以备份和恢复独立的分区 ### 限制 1. 一个表最多只能有1024个分区 2. 5.1版本中,分区表表达式必须是整数,5.5可以使用列分区 3. 分区字段中如果有主键和唯一索引列,那么主键列和唯一列都必须包含进来 4. 分区表中无法使用外键约束 5. 需要对现有表的结构进行修改 6. 所有分区都必须使用相同的存储引擎 7. 分区函数中可以使用的函数和表达式会有一些限制 8. 某些存储引擎不支持分区 9. 对于 MYISAM的分区表,不能使用 load index into cache 10. 对于 MYISAM表,使用分区表时需要打开更多的文件描述符 ## 分库分表的原理 ### 工作原理 通过一些HASH算法或者工具实现将一张数据表垂直或者水平进行物理切分 ### 适用场景 1. 单表记录条数达到百万到千万级别时 2. 解决表锁的问题 ### 分表方式 #### 水平分割 表很大,分割后可以降低在查询时需要读的数据和索引的页数,同时也降低了索引的层数,提高查询速度 使用场景 1. 表中的数据本身就有独立性,例如表中分别记录各个地区的数据或者不同时期的数据,特别是有些数据常用,有些不常用 2. 需要把数据存放在多个介质上 水平分表缺点 1. 给应用增加复杂度,通常查询时需要多个表名,查询所有数据都需 `UNION` 操作 2. 在许多数据库应用中,这种复杂性会超过它带来的优点,查询时会增加读一个索引层的磁盘次数 ### 垂直分表 把主键和一些列放在一个表,然后把主键和另外的列放在另一个表中,就是多一张详情表 使用场景 1. 如果一个表中某些列常用,而另外一些列不常用 2. 可以使数据行变小,一个数据页能存储更多数据,查询时减少I/O次数 垂直分表缺点 1. 管理冗余列,查询所有数据需要JoIN操作 ## MYSQL的复制原理及负载均衡 ### MYSQL主从复制工作原理 在主库上把数据更改记录到二进制日志 从库将主库的日志复制到自己的中继日志 从库读取中继日志中的事件,将其重放到从库数据中 ### MYSQL主从复制解决的问题 数据分布:随意停止或开始复制,并在不同地理位置分布数据备份 负载均衡:降低单个服务器的压力 高可用和故障切换:帮助应用程序避免单点失败 升级测试:可以使用更高版本的 MYSQL作为从库 ### 解题方法 充分掌握分区和分表的工作原理和适用场景,在面试中,此类题通 常比较灵活,会给一些现有公司遇到问题的场景,大家可以根据分 区和分表以及Mysα复制、负载均衡的适用场景来根据情况进行 回答。