MySQL学习笔记

事务隔离级别的理解

假设有A,B两个事务

  • 未提交读:B事务能读到A事务还未提交的修改 几乎只有坏处没有好处的级别
  • 提交读:B事务能读到A事务提交后的修改,可能导致B事务内两次查询得到的结果不一样
  • 可重复读:B事务多次进行相同的查询,读到的同一条记录的结果一致,即使在中间A事务对这条记录进行了修改。但是仍然可能有“幻读”,即A事务在多个查询中间插入了新数据,B事务查到的结果会不一致。
  • 串行化:顾名思义,将操作穿行执行。

引擎特征

  • InnoDB 支持事务和行级锁,支持自动增量列,且自动增长列必须是索引(联合索引必须是第一列),支持外键(然而我斌不想用=。=)
  • MyISAM 支持全文索引,对导入后不再修改的表进行压缩。适合读写操作多,修改删除少,对事务/并发要求不高的场景。

索引特征

B-Tree索引支持较多的匹配方式:

  • 全值匹配
  • 匹配最左前缀(联合索引的第一项或者左边几项)
  • 匹配列前缀(like ‘xxx%’)
  • 精确匹配某一列并范围匹配另一列(a=x and b < y)

而Hash索引则只支持较少的匹配方式,如果某一列使用了范围匹配,则其右边的列都不能使用索引。hash索引只在Memory引擎中支持,仅在特殊场景下适用。但是显然,在hash冲突较少的情况下,通过hash算法来定位数据的性能是非常高的。

索引策略

  • 不要使用计算列 (where a + 1 = 2)
  • 选用适当长度的前缀索引来提高索引的区分度
  • 在多个条件的情况下,使用联合索引
  • 将选择性更高的索引放在左边
    假设我们有一张user表,有性别和年龄字段
    select count(distinct(gender)) from user;
    结果是3(男,女,未知)
    select count(distinct(age) from user;
    结果是100
    那么如果需要同时根据性别和年龄筛user,建立(age, gender)索引的性能会比(gender, age)的性能更高。但是,就这个例子而言,我们并不一定要建立(age, gender)的索引。一般来说,对年龄的匹配更多是范围匹配,而对性别的匹配则是全值匹配,如果使用(age, gender)索引,而且对年龄进行范围匹配查询的话,性别列就不能使用索引了。因为查询使用索引的最左前缀,直到遇到第一个范围匹配条件列。在可穷举而且数量较少的范围匹配条件里,我们可以用 IN 关键字来列举来确保后面的索引列也能用到。例如:select * from user where gender in (‘male’, ‘female’) and age > 18

  • 为了尽可能多的用上索引列,我们应该尽量避免使用多个范围匹配条件(原因不再赘述)

查询优化

  • 不要查询不必要的数据行/不必要的数据列
  • 减少不必要的扫描行数 (例如对无索引的列为条件进行查找,将会导致全表扫描)
  • 尽量使用索引生成的排序结果 否则将使用内存排序甚至文件排序(filesort)
  • 使用关联查询时,确保在ON或者USING子句的列上有索引
  • 使用关联查询时,GROUP BY或者ORDER BY的表达式只涉及一个表中的列,才有机会使用索引优化
  • 适当冗余数据列避免联合查询/子查询

常用优化

  • 批量插入时,使用多值语句将减少大量与数据库之间创建连接/关闭连接等操作的时间。例如 insert into user values(1, ‘male’), (2, ‘female’)……
  • 导入大量数据时,按照索引产生的排序顺序插入可以加快插入效率
  • group by 语句会后面的字段进行排序,如果想好要避免排序结果消耗时间,可以加上order by null 禁止排序
  • order by语句可以借助索引生成的排序,前提是where条件和order by使用的是小童的索引,而且order by的顺序与索引生成的排序顺序相同。如果有多个order by 字段,这些字段需要都是升序或者都是降序。
    示例:可以利用索引的order by 语句

    • 在有此时有(key_part1, key_part2) 的联合索引的情况下,select * from xxx order by (key_part1, key_part2)
    • select * from table where a = 1 order by a desc, b desc

    不能使用索引的order by 语句:

    • select * from table order by a desc, b asc
    • select * from table where a = 1 order by b desc
    • sekect * from table order a, b
Author: rainj2013
Link: https://rainj2013.top/2018/10/18/MySQL学习笔记/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.