1. SQL没加索引

SQL的索引通常由B+树实现。 B+树是自平衡的,支持单值查询,范围查询。 当我们的查询走索引时,能够非常快的找到需要的数据。

然而,当我们查询的数据没有走索引时,就需要全表扫描,会非常慢。

因此,我们在设计数据库时,需要给经常被查询的列建立索引。

2. SQL索引不生效

在书写SQL语句时,也要注意:

(1) 将带索引的行尽可能的往前写

(2) 不要在索引列上进行计算

(3) 不要给索引行进行类型转换,这是变相的给索引列加计算

(4) 前导模糊查询不会使用索引

(5) 联合索引最左前缀原则,设计联合索引时需要将区分度最高的列放在最前面

(6) 负向条件索引不会使用索引,!=, <>, not in, not exists, not like

(7) 建立非主键的非聚集索引,回表查询数据

(8) 明确知道只会返回一条记录,可以加limit 1, 让MySQL的游标停止移动

(9) 对文本建立前缀索引

(10) 建立的索引列不为null,null不会被包含在索引中

(11) 优化器选错了索引

3. limit深分页问题

(1)标签记录法 where x > offest limit 10

(2)延迟关联法 先查找满足要求的主键ID,在与主键ID inner join,更精确地查找数据

4. 单表数据量太大

(1) InnoDB最小存储单元是页,一页大小为16k。

如果一行的数据大小为1k,单个叶子结点可以记录的数据为16k/1k = 16

非叶子结点指针数据:bigint ID, 8字节,指针大小为6字节,总:14字节,16k/14B = 16 * 1024 B / 14 B = 1170

高度为2的树 : 1170 * 16 = 18720

高度为3的树: 1170 * 1170 * 16 = 21902400, 2千万。

如果存储更多的数据,树的层级会变高,经历更多的磁盘IO,查询性能会变慢。

(2)可以考虑分库分表

5. join或者子查询过多

(1)一般不建议使用子查询

(2)不要有3个以上的表连接

(3)join关联的字段需要加索引

(4)如果需要更多的表,可以从代码层面进行拆解

6. in元素过多

建议不超过500个

7. 数据库刷脏页

内存和磁盘不一致,称为脏页。 内存写入到磁盘后,变成干净页。

更改数据时,先更新内存,写入redo log, 执行器生成bin log,并且入磁盘,调用提交事务引擎,把redo log 改成commit状态, 更新完成。

这一步只把日志更新到磁盘,没更新数据。空闲的时候才把redo log里的数据更新到磁盘中。

刷脏页时机:

(1)redo log 满了

(2)内存不够

(3)系统空闲

(4)MySQL正常关闭

8. order by Using filesort 文件排序

当需要排序的数量大于 sort buffer, 会利用磁盘存储中间数据(归并)

(1)rowid排序

(2)全字段排序

9. 拿不到锁

需要等待锁释放,可以通过show processlist, 查看当前语句处于什么状态

10. delete + in 子查询 不走索引

select in 子查询可以走索引

11. group by 使用临时表

使用临时表,又默认会进行排序

优化方案:

(1)加索引

(2)order by null

(3)只使用内存临时表

(4)使用SQL_BIG_RESULT

12. 系统硬件或网络资源

高并发,IO/CPU利用率高

13. 测试和生产数据库环境参数配置不一致

index merge