当前位置: 首页 > 科技观察

MySQL:优化SQL的五个常用技巧

时间:2023-03-15 18:57:27 科技观察

SQL命令以其简单的语法和高效的操作而受到许多用户的欢迎。但是我们经常会遇到质量低下或者性能极差的SQL语句。这时候大多数人会想:重构这条SQL语句,保持查询的结果集和原来一样,希望能提高SQL的性能。其实在重构SQL的时候,我们可以使用一些技巧,让我们的优化工作变得更加简单。分解SQL面对一个复杂的SQL,我们可以将它分解成多个简单的SQL。即使变得更简单,我们仍然可以得到相同的处理结果。复杂的SQL通常出现在一些老的产品和项目中,因为以前的开发人员认为,多次交互在网络带宽、程序和数据库之间的网络通信等方面是一件代价高昂的事情。不过现在的技术发展已经可以解决这个不足了,因为跑多条SQL已经不是问题了。复杂SQL分解,面对超级复杂的SQL语句,性能提升尤为明显。因此,当面对超复杂的SQL语句和性能问题时,建议将其分解成小的查询进行优化。但是,在应用设计的时候,如果一个查询是胜任的,不会造成性能问题,可以用稍微复杂的SQL来完成。生硬地把它拆分成多个小查询是不明智的。在当今很多高性能应用系统中,强烈推荐使用单表操作,然后在应用中关联单表查询结果,以满足复杂业务的查询需求。**一条SQL就搞定了,为什么要单独写,还要在应用中多次执行SQL查询,然后关联结果集,为什么要这样做?这样做乍一看并不复杂本来是一个query,结果变成了多个query也不好说。事实上,这种分解有以下优点:使缓存更有效率。在应用程序中,可以方便的缓存单表查询结果对应的结果对象,方便以后随时直接从结果对象中获取数据。分解查询后,执行单个查询可减少对表锁的争用。通过在程序应用层进行关联,更容易拆分数据库,更容易实现高性能和可扩展性。单表查询比多表复杂查询效率更高。减少对冗余记录的查询。在程序应用层进行关联是指应用只需要查询某条记录一次,而在数据库中进行关联查询可能需要重复访问某些数据记录。从这个角度来看,这样的重构也可能会减少网络和内存消耗。QuerySegmentation有时候对于一个大查询,也就是一个结果集很大的查询,我们需要采用“分而治之”的思想,将大查询切分成小查询。每个查询的功能完全一样,只完成了一小部分。一次只返回一小部分查询结果。通俗地说,就是对where条件的过滤范围进行分段,每次只查询一部分数据,也就是类似于分页查询。这样无论对于SQL查询本身还是对于上层业务来说都是非常小的开销。最典型的案例就是分页查询。目前各种框架都有很好的支持,比如MyBatis等,注意实际使用可以避免。执行计划通过执行计划的EXPLAIN关键字,我们可以知道MySQL是如何执行SQL语句的,这可以帮助我们分析我们的查询语句或者表结构的性能瓶颈。EXPLAIN的查询结果还会告诉我们索引主键是怎么用的,数据表是怎么查找或者排序的……等等。语法格式为:EXPLAINSELECT语句;通过执行计划结果,会指导我们进一步重构SQL语句,比如:添加索引,调整索引顺序,避免使用某些函数等等。平时写SQL要遵循原则,养成良好的习惯,多加注意,很大程度上避免一些SQL性能问题。总结如下:始终为每个表设置一个ID主键。避免使用SELECT*。索引搜索字段。连接表时使用相应类型的列,并对其进行索引。尽可能使用NOTNULL。较小的列会更快。当只有一行数据时使用LIMIT1。运算符优化,尽量不要使用不利于索引的运算符,目的是避免全表扫描。1)谨慎使用in和notin,尽量使用between而不是in,使用notexists而不是notin2)谨慎使用isnull和isnotnull3)!=或<>运算符可以不用它,否则引擎将放弃使用索引进行全表扫描。...使用查询缓存当许多相同的查询被多次执行时,这些查询的结果将被放入缓存中,以便后续相同的查询可以直接访问缓存的结果而无需操作。MySQL查询缓存保存查询返回的完整结果。当查询命中缓存时,MySQL将返回类似的结果,跳过解析、优化和执行截断。这是提高查询性能最有效的方法之一,由MySQL引擎处理。通常,MySQL默认不启用查询缓存,需要手动启用。查询缓存对应用程序是完全透明的。应用程序不需要关心MySQL是通过查询还是实际执行返回结果。事实上,这两种方法的结果是完全一样的。换句话说,查询缓存不需要任何语法。随着今天的通用服务器变得越来越强大,查询缓存已被发现是影响服务器可扩展性的一个因素。它可能成为整个服务器资源争用的单一点,并且在多核服务器上,可能导致服务器僵尸。所以大多数时候,查询缓存应该默认关闭。如果查询缓存非常有用,可以配置几十兆的小缓存空间。(选择时需要权衡)关于查询缓存,可以配置以下参数:query_cache_type是否开启查询缓存。您可以设置OFF、ON和DEMAND。DEMAND表示只有查询语句中明确写入sql_cache的语句才会放入查询缓存。query_cache_size查询缓存使用的总内存空间,以字节为单位。这个值必须是1024的整数倍,否则实际分配的数据会和指定的大小不同。query_cache_min_res_unit在查询缓存中分配内存块时的最小单位。query_cache_limit缓存的最大查询结果。如果查询结果大于这个值,则不会缓存。因为查询缓存在数据产生的时候就开始尝试缓存数据,所以MySQL只有在所有的结果都返回后才知道查询结果是否超过了限制。