联合索引
联合索引按顺序abc
1、select * from table where a<xxx and b=xxx and c=xxx;
一般情况下不走索引,当联合索引第一个就按范围查找,mysql的算法会认为其寻找范围很大,其效率还不如全表扫描直接不走索引转而走全表扫描;
2、select * from table for index(联合索引名) where a<xxx and b=xxx and c=xxx;
这种加了for index会强制走索引,但一般不用。mysql底层算法一般比我们自己去强制走算法快的多。除非个别情况下你自认为走索引一定快才使用;
3、select c,b,a from table where a<xxx and b=xxx and c=xxx;
覆盖索引:所有的字段都在索引中,直接在索引中就能找出结果集,不需要回表再去找一遍,这种情况下,肯定是走索引会更快。
4、in 和 or在数据量比较大的时候会走索引,否则走全表扫描;
5、select * from table where a like ”%xx“ and b=xxx and c=xxx;
like语句,当%号在前面的时候,一般都会走索引;在新版本的mysql引入了索引下推的概念,当联合索引的第一个使用的是like语句且%在前面的时候,新版本的mysql基本上都会走索引,把索引中b和c的结果集从索引中拿出来,回表一一比对;
join优化
尽量将大表的连接字段建立为索引;join需要小表作为驱动表效率才会高,一般情况下mysql会自动将小表作为驱动表,但是也会有部分情况下,会分析错误,比如两个表数据比较接近的时候这时我们可以使用straight_join(仅限内连接)连接两表,将小表放在前面,这样就会将左边的表设定为驱动表;一般join就这些优化方式,join是很难优化的,所以一个业务如果可以尽量只建立一张表,如果非要建立多张表,必定不能超过3张表(报表等特殊除外);否则join难以优化,数据量大的时候速度会变的很慢;
分页查询优化
当数量达到一定级别的时候,分页到了后面速度会变的很慢;
当以自增连续的主键(不能断开),先判断大小再limit分页
当不满足以上条件时,可以先使用覆盖索引查出满足条件的索引,因为时覆盖索引,所以效率较高,然后使用join in 查出所有数据效率高;
count(1)≈count(星)>count(索引)>count(主键);
以上四种效率都i很高,基本没什么差别,count(星)的效率也是极高,不会像之前别人说得会取出所有的字段。至少在mysql中是这样的。
前两个都是根据索引直接取出行数,所以效率要比count(索引)要高些,索引还要取出字段,count(主键)则是最慢的,因为主键是和数据绑定在一起的。
估算全表数据,不准确但效率高
show table status like ”tablenname“
in和exits的效率对比
首先要服从小表优先原则,而in是先扫描括号里面的表,再把数据与外面的表一一比对。而exits则相反;
所以如果是小表在里面则用in,如果是小表在外面则使用exits;如果是exits则最好使用join in替代,效率要高;
数据库相关一些知识
先做业务,再做索引;
唯一约束不一定要是索引,去约束数据的唯一性是很重要的;
单表数据超过500万或者单表容量超过200万才推荐分库分表;
超过三个表最好不要用join,join难以优化;能不用join最好一个都不要用;
能用java做的就不要用数据库来做,数据库优化是非常困难的。而java环境优化相对简单的多。所以数据库的资源是非常珍贵的。尽量sql语句能简单就简单。把复杂的计算交给java来做;
orcale与mysql在单台上orcale的效率远远高于mysql,但是orcale的扩展性远不如mysql所以大公司一般都用mysql而不使用orcale;
in的操作能避免就避免,不能避免也必须控制在1000以内,否则效率低下;
事务特性ACID
原子性:一个事务里。所有语句要吗全部成功,要吗全部失败;
一致性:跟原子性有点类似,如:订单量+1,库存量-1,积分量+1必须要同步操作。
隔离性:事务与事务之间的数据不会互相干扰;
持久性:不去删除就永久存在;
并发事务带来的问题
更新丢失:多个事务同时修改一个数据,该数据前面做的所有操作,被最后一步的更新覆盖了;
脏读:一个事务还没有提交,另一个事务就读取到了这个还没有提交的数据;
不可重复读:一个数据在被读取到事务中后,该事务读取该数据,前后不一致;
幻读:在sql语句一样的情况下,读取到比原来更多的数据;
事务隔离级别
读未提交:脏读,不可重复度,幻读;
读已提交:不可重复读,幻读;
可重复度:幻读;(数据库默认级别,一般都是用这个)
可串行化:没有任何问题,但是效率很低,几乎没什么人去用
锁
机制分;
乐观锁:版本号比对,加一个版本字段,不断更新,类似cas机制;
悲观锁:直接将数据锁住;
表锁:一般不用,数据迁移的时候可以用用;
行锁:一般都时用行锁,加锁慢,开销大,粒度小;
表锁直接给该表加上锁标记,速度肯定很快,行锁需要通过扫描索引之类的找到改行,给改行加上锁,所以效率没那么高;
间隙锁:
锁住数据之间的间隙,与默认的事务隔离级别,可重复度可以解决幻读问题;
如:
表中有数据 1,2,3,10,20
update account set name = ‘xxx’ where id > 8 and id <18;
那么像上面这条语句锁住的间隙时3-20之间的间隙,因为8处于3-10的间隙中,18处于10-20的间隙中。所以锁住了他们的间隙,3-20(包含20,不包含3)的数据将不能做任何修改,添加;如果是
update account set name = ‘xxx’ where id > 8 and id <25;
那么该间隙锁会锁住3-无穷大;
无索引的行锁会变成表锁,很危险,效率将会变的很低,需要注意(update语句);
锁是可以通过操作kill掉的。