mysql 的一些 优化经验 记录

1,将一个大连接查询(JOIN)分解成对每一个表进行一次单表查询,然后将结果在应用程序中进行关联,这样做的好处有:

  • 让缓存更高效。对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。
  • 分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余记录的查询。
  • 减少锁竞争;
  • 在应用层进行连接,可以更容易对数据库进行拆分,从而更容易做到高性能和可扩展。
  • 查询本身效率也可能会有所提升。例如下面的例子中,使用 IN() 代替连接查询,可以让 MySQL 按照 ID 顺序进行查询,这可能比随机的连接要更高效。
SELECT * FROM tab
JOIN tag_post ON tag_post.tag_id=tag.id
JOIN post ON tag_post.post_id=post.id
WHERE tag.tag='mysql';
SELECT * FROM tag WHERE tag='mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);

2,mysql的查询语句执行流程。

     2.1、client和server建立连接,client发送sql至server(对应连接器这一过程)

     2.2、server如果在查询缓存中发现了该sql,则直接使用查询缓存的结果返回给client,如果查询缓存中没有,则进入下面的步骤(对应查询缓存这一过程,8.0这一过程已经不存在了,8.0完全抛弃了这个功能)

     2.3、server对sql进行语法分析,识别出sql里面的字符串是否符合标准,比如select关键字不能写错(对应分析器这一过程)

     2.4、server对sql进行语义分析,识别出sql里面的字符串的具体意思是什么,比如T1是表名,C1是列名(对应分析器这一过程。3、4步其实解析的过程,这个解析的过程是分析器的工作不是优化器的工作)

     2.5、server确定sql的执行路径,比如走索引还是全表,多表连接时哪张表先走哪张表后走,当你的where条件的可读性和效率有冲突时mysql内部还会自动进行优化,也就是大家理解的重写where子句(对应优化器这一过程)

     2.6、server对执行sql的用户进行权限检查,比如对表是否有权限执行(对应执行器这一过程)

     2.7、server执行该sql语句,发送结果给client(对应执行器这一过程)

      连接器-->查询缓存-->分析器-->优化器-->执行器

        这里需要注意的是  

            1,设置查询缓存 query_cache_type和query_cache_size,对应上面的第二步,注意 语句是区分大小写的。

            2,在第5步时,优化器自动优化,也就是我们常用的查看执行器。看优化器后语句的执行过程,当然我们也可以

                 干扰优化器,让sql按我们的想法去用索引,通过FORCE INDEX(索引1[,索引2])或者使用USE INDEX(索引1[,索引2]),比如:select t1,t2 from table1    FORCE INDEX( index_t1)  where t2=1 and t1=2

                 或者是忽略索引,IGNORE INDEX(索引1[,索引2])。

            3,注意聚集索引和非聚集索引,表的引擎主要分InnoDB和MyisAm

                  MyisAm主要使用的就是非聚集索引,InnoDB主要使用的是聚集索引

                  聚集索引的索引和数据在一个文件,非聚集索引的索引和数据是分开的,但都是使用的B+树的结构

                当我们使用聚集索引去查询数据的时候,一般是主键,mysql通过一次检索就可以将数据返回,因为索引和

               数据是在一个节点文件上,

                当使用非聚集索引去查询数据时,mysql通过非聚集索引先检索到聚集索引,在通过聚集索引再去检索数据

                 这个就是所谓的回表查询,这样会增大检索开销。

                那我们怎么样去避免mysql的二次回表查询?其实我们查询的时候可以多用联合索引,

              比如字段 a,b,c我们建立的联合索引,根据索引最左匹配原则,相当于建立的 a,ab,abc三个索引

               而且当我们查询想为a,b,c是:select a,b from t where a=1 and b=2 and c=4 时,

              虽然他是个非聚集索引,但是我要返回的字段正好在我的索引项目上,不需要去回表查询聚集索引勒,

              这个就是我们常说的索引覆盖。大大增加勒查询效率。

              4,因为我们大部分表都是InnoDB,并且聚集索引都是主键,结构是b+tree结构,主键索引和数据在同一个叶子节点。

               而B+tree是有顺序的,所以当我们的数据插入进来的时候,它会根据主键来重排,导致B+tree的数据需要重排,

               会加大mysql开销,所以我们在设计主键的时候,尽量也整形或者长整形,因为占的字节少,比较大小也容易,

              而且最好主键是单调递增的,这样的话,我们在插入数据的时候,因为是递增的,所以这样能够很大的减少索引的重排,这样也会大大减少mysql的开销。

猜你喜欢

转载自blog.csdn.net/shrek11/article/details/103977653