事务隔离级别的理解
假设有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