51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 1370|回复: 4
打印 上一主题 下一主题

复合索引是否会被使用的条件

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2016-5-3 16:52:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 stacktestor 于 2016-5-3 17:44 编辑

背景:
今天,接到一个项目的项目经理电话,告之说生产环境有几个查询超级慢,就是查询单张表的数据,查询条件也很简单,但是加了索引以后并没有走索引,依然还是走的全表扫描。
听到该问题描述,我开始浮想联翩,统计信息太旧?存在隐式转换?索引树倾斜度太高,导致oracle认为走索引的成本更高?
带着各种可能的原因猜想,火速赶到了现场,发现原来都是我想多了。不走索引单纯是建立的索引不合理,查询条件是多个字段,应该建立复合索引,现场维护人员只对其中单个字段建立了索引,ORACLE认为不如走全表扫描开销小,所以没走索引。
汗~~~~~~
添加索引的时候发现,几个不同的查询,查询条件字段都一样,但是写的顺序却不一样(开发写SQL太随意了!!!!字段一样,顺序也写成一样啊!!!!!!!),结果先剧透一下,同样也是可以走索引的。而由此联想到些问题,于是在解决完效率问题后,在个人环境上做了一个验证。
这个就是完整的背景。

---------------------------------------------------
验证内容:
ORACLE 11GR2 复合索引的使用条件。
前提条件:
创建一张表,并对字段A、B建立组合索引,顺序为index(A、B);
测试场景:
针对以下6个场景进行测试:
1、查询条件为:A='XXX' and B='YYY';  顺序完全一致的情况;
2、查询条件为:B='YYY' and A='XXX';  顺序不一致的情况;
3、查询条件为:A='XXX';              单个字段且为复合索引前导列的情况;
4、查询条件为:B='YYY';              单个字段且不是复合索引前导列的情况;
5、查询条件为:C='ZZZ' and A='XXX';  查询条件既包含其它字段,也包含复合索引前导列的情况;
6、查询条件为:C='ZZZ' and B='YYY';  查询条件既包含其它字段,也包含复合索引非前导列字段的情况;
7、查询条件为:C='ZZZ' and A='XXX' and B='YYY';  查询条件除复核索引字段外还包括其它字段,且索引外字段在第一位;

---------------------------------------------------
执行过程:

创建测试数据:
create table test_index_demo(recid  RAW(16) not null,customer_id RAW(16) not null,product_id  RAW(16) not null)
create unique index index_test on test_index_demo (CUSTOMER_ID, PRODUCT_ID)
根据查询字段做笛卡尔积准备了将近3000万数据;
exec dbms_stats.gather_index_stats(ownname => 'gboss',indname =>'test_index_demo');

分别针对每个场景进行测试,查看执行计划如下:
场景一:
select * from TEST_INDEX_DEMO T WHERE T.CUSTOMER_ID=HEXTORAW('01540EAA1D8E690099261D41257815D9') AND T.PRODUCT_ID=HEXTORAW('01540EAB83EC6900E30EAD424661D792');

此处是走索引的,符合预期;

场景二:
select * from TEST_INDEX_DEMO T WHERE T.PRODUCT_ID=HEXTORAW('01540EAB83EC6900E30EAD424661D792') AND T.CUSTOMER_ID=HEXTORAW('01540EAA1D8E690099261D41257815D9');

此处可以看到ORACLE的优化器实际上把查询条件的顺序进行了调整,所以同样走了索引,符合预期;

场景三:
select * from TEST_INDEX_DEMO T WHERE T.CUSTOMER_ID=HEXTORAW('01540EAA1D8E690099261D41257815D9');

此处因为查询条件为复合索引的前导列,所以走了索引,符合预期;

场景四:
select * from TEST_INDEX_DEMO T WHERE T.PRODUCT_ID=HEXTORAW('01540EAB83EC6900E30EAD424661D792');

此处没有走索引,走的全表扫描,我原本以为即便不是复合索引的前导列,也会走索引的,看来我原来的认识是错误的。
针对这个我特意临时添加了index(B、A)验证了一下,是因为查询条件字段不是复合索引前导列导致,还是因为出于其它方面的成本考虑,测试发现,添加了index(B、A)顺序的索引后,该SQL就可以走索引了,所以应该可以认为是查询条件字段不是复合索引前导列导致的。

场景五:
select * from TEST_INDEX_DEMO T WHERE
T.RECID=HEXTORAW('01540ED5DA7069465FB7E42D07EDC156') AND T.CUSTOMER_ID=HEXTORAW('01540EAA1D8E690099261D41257815D9');

ORACLE优化器并没有调整查询条件字段的顺序,但是依然走了索引。走索引是符合预期的,但是我原本以后应该会改变字段顺序的,这块我有点不太理解,如果有看到这篇日志的大牛请帮忙解惑一下,谢谢。

场景六:
select * from TEST_INDEX_DEMO T WHERE
T.RECID=HEXTORAW('01540ED5DA7A69461D878CAE1CED2B7E') AND T.PRODUCT_ID=HEXTORAW('01540EAB83EC6900E30EAD424661D792');

此处没有走索引,倒是符合预期,汗~~~~

场景七:
select * from TEST_INDEX_DEMO T WHERE
T.RECID=HEXTORAW('01540ED5DA7A69461D878CAE1CED2B7E') AND T.CUSTOMER_ID=HEXTORAW('01540EAA1D8E690099261D41257815D9') AND T.PRODUCT_ID=HEXTORAW('01540EAB83EC6900E30EAD424661D792');

此处走索引了,结果倒是符合预期。

----------------------------------------------------
结果对比及结论:
所以经此对比,我的结论是:
1、查询条件字段与复合索引字段一致的,无论顺序如何,ORACLE优化器会自动调整顺序,结论是会走索引;
2、查询条件字段与复合索引字段不一致,查询条件字段包含复合索引前导列的,可以走索引;不包含索引前导列,则不走索引;
--------------------------
所以,由此结论可以看出,在设计查询的时候,还是应该要求开发在组织SQL的时候对于第一个查询条件该用哪个字段还是需要综合考虑系统所有查询来进行设计一下的。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

该用户从未签到

2#
 楼主| 发表于 2016-5-3 17:00:11 | 只看该作者
咦~~~奇怪,在论坛竟然可以发出来,
不知道为什么在我个人的空间日志却不能发布,说是含有网站的屏蔽词语。
实在是不知道哪个词语是啊,汗~~~
回复 支持 反对

使用道具 举报

  • TA的每日心情
    无聊
    昨天 09:19
  • 签到天数: 933 天

    连续签到: 5 天

    [LV.10]测试总司令

    3#
    发表于 2016-5-4 09:57:43 | 只看该作者
    stacktestor 发表于 2016-5-3 17:00
    咦~~~奇怪,在论坛竟然可以发出来,
    不知道为什么在我个人的空间日志却不能发布,说是含有网站的屏蔽词语 ...

    你如果在空间遇到这个情况,可能进入审核,到时候我们会有相关人员进行查看的。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    4#
     楼主| 发表于 2016-5-4 16:01:47 | 只看该作者
    lsekfe 发表于 2016-5-4 09:57
    你如果在空间遇到这个情况,可能进入审核,到时候我们会有相关人员进行查看的。

    是的,今天我看到我空间的帖子也从垃圾站发表出来了。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 09:19
  • 签到天数: 933 天

    连续签到: 5 天

    [LV.10]测试总司令

    5#
    发表于 2016-5-4 16:34:03 | 只看该作者
    stacktestor 发表于 2016-5-4 16:01
    是的,今天我看到我空间的帖子也从垃圾站发表出来了。

    这个屏蔽字出现会进入垃圾箱的 ,不过我们到时候都会审核的。所以你放心好了。
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-4-20 04:23 , Processed in 0.064436 second(s), 22 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表