1.1select字句中不要使用* 理由:把*替换成表中的字段名,需要解析一次数据字典,有性能损耗
1.2from字句后的主表最好是记录数最少的表(oracle rbo模式,从from最右边的表开始扫描)
1.3范围大的条件放在where末尾,where字句的解析顺序是从后到前
1.4子查询in迭代的是子表,exists迭代的是外表,外大用in,内大用exists
1.5无论何时not exists由于not in
1.6mysql中 join 子查询 性能高于 where 子查询
1.7存在null值的列随数据分布情况,可能不走索引,count不字句不计算含有null值的记录
1.8like字句左%不会使用索引
1.9order by后尽量使用索引列排序,多个排序字段含有不同的索引时也会导致索引失效
1.10索引列不能是表达式的一部分
不使用索引:select uid from user where uid + 1 = 2;
使用索引:select uid from user where uid = 2 - 1;
1.11范围查询时尽可能缩小范围
1.12子查询不易嵌套过多层
[RU]读未提交:脏读、不可重复读、幻读
[RC]读已提交:会出现不可重复读、幻读,避免脏读
[RR]可重复读:会出现幻读,避免不可重复读,脏读
[Serializable]串行化:脏读,不可重复读,幻读都避免,性能差
脏读:事务A读到了事务B还没有提交的数据
不可重复读:事务A中多次读取到的数据不一致
幻读:两个并发的事务中其中一个发生了插入、删除操作,被另一个事务提交前读取到
spring事务传播行为
1.如果有,则加入,没有则新建(默认) REQUIRED 受父事务影响,影响父事务
2.如果有,则挂起,新建事务,没有则新建,REQUIRED_NEW 不受父事务影响,不影响父事务
3.如果有,则加入,没有就抛出异常
4.如果有,则加入,没有则以没有事务方式执行
支持事务 | 锁粒度 | 存储 | 外键 | 全文索引 | 树索引 | |
MyISAM | N | 表锁 | 256TB | N | Y | Y |
MEMORY | N | 表锁 | RAM | N | N | Y |
InnoDB(默认) | Y | 行锁、表锁 | 64TB | Y | N | Y |
Archive | N | 页锁、表锁 | NONE | N | N | N |
Archive使用场景为只有大量的select或insert语句
行锁:通过给索引上的索引项加锁来实现行锁,意味着如果sql语句没有使用到索引,是不会加行锁的,只会加表锁,有死锁产生的可能
页锁:页锁是位于行锁和表锁之间的,性能也在两者之间
表锁:顾名思义,给全表加锁,所以不会产生死锁
死锁:并发的两个事物中,A事物锁定xx主键索引等待xx其他索引,B事物锁定了xx其他索引等待xx主键索引,则引发死锁
共享锁:其实就是读锁,语法select ... lock in share mode。其他事务可以读取,可以再加共享锁,不可以加排他锁。
排它锁:排它锁就是写锁,语法select ... for update。其他事务不可读,不可加任何锁,只能阻塞等锁释放,mysql innodb中默认会为update、delete、insert操作加排他锁。
如何尽可能避免死锁:
1、以固定的顺序访问表和行。比如两个更新数据的事务,事务A 更新数据的顺序 为1,2;事务B更新数据的顺序为2,1。这样便可能会造成死锁。
2、大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。
3、在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。
4、降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。
5、为表添加合理的索引。可以看到如果不走索引将会为表的每一行记录添加上锁,死锁的概率大大增大
普通索引、普通联合索引
唯一索引、唯一联合索引
添加索引:ALTER table table_name ADD INDEX index_name (column_list)
删除:DROP INDEX [indexName] ON tableName;
ALTER TABLE table_name ADD UNIQUE index_name (column_list)
显示索引信息:SHOW INDEX FROM table_name;
explan sql语句
type:all全表扫描、index、range、const 性能一次降低
possible_keys: 可能使用的索引
key:实际使用到的索引
rows:sql语句扫描了多少行