近期某生产系统在经过磁盘存储更换后,仍存在存储IO较慢的情况,于是想从数据库侧进行SQL的优化--关于应用在使用过程中发现web界面涉及到数据库的某些相关查询十分慢(最大约5分钟)。
根据现象描述对web上的相关查询较慢的菜单进行了统计,得出SQL在数据库中常用的查询where条件字段,采取如下动作:
1) 当晚对用户收集了统计信息,第二天再次查询,发现较为好转(有些之前查询较慢的,现在查出正常),但仍存在有些SQL较慢的现象,于是进一步分析。
2) 找出仍较慢的SQL语句如下:
此count(*)语句在界面的主要作用是总行查询500多个XXXX行数,然后在web做分页;十分慢(还是约耗时5分钟),不管走不走索引,原因是where条件中的4个字段选择性都很底,根本没有任何选择度(放弃索引)。
主要慢的原因是like条件(匹配全行1%),要在1千8百多万里边做模糊查询且字段较长且区分度十分低。此表是TP型不适合建位图索引,所以经询问应用有另外一张表YYYY,此表记录了相关数据并且数量只有500条,于是将此表与YYYY进行了关联,并使用了YYY来做关联,把组合索引建相关字段上边。
删除之前的不正确的组合索引,按所需的顺序创建新的两个组合索引。
然后收集整个表及索引的统计信息。
改写之前的慢SQL(5分钟)如下:
主要是将原来的在大表中去like改成用in替换,然后在小表中去like。
查询执行时间从原来的5分钟降到了现在的6秒!计划如下:
可以看到:netst loop index join2 一个非常好的执行计划,结果集较少的小表数据驱动大表(走了索引)且代价较低,效率提高!
其实对于in的写法并不是十分好的写法(但对于本处案例来说是可以了的),当然还有等值连接写法代替in。
从字段长度很长、区分度不高且千万级的大表且字段超长的表里边去做like动作是非常慢的,可以变相的尝试如下方法:
1、 用in(如果没有现成的表,例如YYYY,则可以通过事务级的临时表解决,即建立事务级临时表,然后将此表与大表in关联,此适合于驱动表是小集合),对于驱动表是大表则可以用exist。
2、 等值联连(netst loop),例如本例的另外一种SQL的写法。
文章
阅读量
获赞