连接查询优化不管是什么数据库,多表连接的查询成本都比较高,所以对于高并发的应用,应该尽量减少连接查询和多表连接数不要超过4个表。一般数据量小的时候,连接也不会太小,一般不会有性能问题。当数据量增大时,性能问题会更加突出。因此,在数据库的前期,最好确定哪些表可以成为大表,然后进行反范式设计,减少连接表的数量,比如增加冗余字段等,或者进行连接业务代码中的计算。一些经验总结点:1.确认ON和USING子句中的列有索引。如果连接顺序是B和A,那么只需要在A表的列上建立索引即可。B中不需要建索引,可以减少不需要索引的开销。查询示例:SELECTB.*,A.*FROMBJOINAONB.col1=A.col2MYSQL会扫描B表的全表,对B表的每一行查找A表的记录,所以需要使用索引在A表的COL2列上,提高效率。2.使用EXPLAIN检查连接并查看ROWS列。如果这个列的值太大,比如几千、几万,那么就需要考虑是不是索引失效了,还是连接表的顺序错了。3.考虑在应用层实现连接查询。例如,您可以将复杂的查询分解为JAVA中的几个简单查询,以获得更小的结果集。处理遍历后,可以根据条件得到完整的数据。这通常更有效率,因为数据的分离使得它不太可能发生变化,有利于数据库缓存数据。示例如下:SELECTa.*FROMAWHEREa.idIN(1,2,3,4,5,6,7,8,9,10);如果id=1~8的记录已经存储在缓存REDIS中,那么我们只需要查询id=9和10的数据即可,减少了很多数据库连接交互,可以提高性能。GROUPBY、DISTINCT、ORDERBY语句优化这些语句默认必须按ORDERBY排序,优化的思路也是类似的。1、如果连接查询多个表,ORDERBY的列应该属于连接顺序中的第一个表。如果不在同一张表中,可以考虑冗余列,或者合并表。2、需要保证索引列和ORDERBY列相同,并且每列的排序方向一致。3.指定ORDERBYNULL。默认情况下,MYSQL将对所有GROUPBY查询进行排序。如果想避免排序结果的消耗,可以指定ORDERBYNULL。例子如下:selectcount(1)fromsys_deptgroupbydept_idorderbynulllimit3子查询优化因为子查询的可读性更符合开发者的思维习惯,所以习惯写子查询,但是子查询是生产环境中最常见的性能瓶颈。对于数据库,在大多数情况下,连接比子查询更快。优化器通常可以生成更好的执行计划、使用余弦加载数据以及更高效地处理查询。子查询生成的临时表没有索引,所以效率会比较低。在目前的实践中,子查询应该尽可能改写为JOIN。举一个常见的例子SELECTc1FROMt1wheret1.c1IN(SELECTc1FROMt2);我们可以将其转化为join方法:SELECTc1FROMt1.c1FROMt1,t2WHEREt1.c1=t2.c2优化IN列表为在IN列表中,MySQL会对其中的值进行排序,使用二分查找的方式定位数据.把IN语句改写成OR形式也没用。IN列表不建议太长,对于高并发业务,建议不要超过几十个。优化思想可以转化为多个相等的查询。比如下面的语句,如果ID值很多,性能就不会很好。SELECT*FROMAwhereA.IDIN(SELECTidFROMB)优化思路:从程序的业务层入手,先查询SELECTidFROMB,然后获取ID的值,逐步与SELECT*FROMA拼接,转化为SELECT*FROMAID=在哪里?形式。优化UNIONUNION语句是默认去除重复记录,需要进行排序操作。如果结果集很大,成本会很高。建议尽量使用UNIONALL语句。对于多UNION分表的场景,尽量在分库的时候进行。,判断每一个分表数据的唯一性,这样就不需要使用UNION去重了。另外,查询语句外的WHERE条件并没有应用于每个单独的UNION子句,所以每个UNION子句都加了一个where条件。优化BLOB和TEXT类型字段的查询。由于mysql内存临时表暂时不支持BLOB和TEXT类型,如果包含在查询中,会使用基于磁盘的临时表,性能会很低。因此,如非必要,不应使用查询条件。这2种。优化思路:1、如果一定要用,可以考虑分表,将BLOB和TEXT字段分离到单独的表中。2、如果有很多大字段,可以考虑将这些字段合并为一个字段。存储一个大的200KB比存储20个10KB效率更高。3.考虑使用COMPRESS(),然后存储。
