重复索引

Gomes 2014-10-23 10:43:07
我的table表下有 pk_table_1(主键 Unique) key cid,datetime
idx_table_1(索引 Unique) key cid,datetime
idx_table_2(索引 Normal) key cid
现在 索引1和主键是重复的。
我查询
slect * from table datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid in (1,2,3)
时为什么是使用 idx_table_2 索引?
...全文
184 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Gomes 2014-10-23
  • 打赏
  • 举报
回复
引用 3 楼 arlen1990 的回复:
[quote=引用 楼主 sm357753 的回复:] 我的table表下有 pk_table_1(主键 Unique) key cid,datetime idx_table_1(索引 Unique) key cid,datetime idx_table_2(索引 Normal) key cid 现在 索引1和主键是重复的。 我查询 select * from table datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid in (1,2,3) 时为什么是使用 idx_table_2 索引?
oracle目前采用最优方案,所以肯定走idx_table_2索引比另外两个效率高。 下面说下我对这个现象的理解: 你这个sql句子对于datetime而言是等值查询,对于cid相当于范围查询,而 oracle的联合索引,字段顺序只有是当等值查询在前,范围查询在后效率才高, 使用联合索引才最优。所以你试试idx_table_1(索引 Unique) key cid,datetime 这个索引改成这样idx_table_1(索引 Unique) key datetime,cid,也就是调换索引 列的顺序。(当然如果要看哪种情况查询多一点,如果这个sql只是偶尔执行一次, 那就不要随意改动了。)这样oracle大概就会使用联合索引了。 [/quote] 我现在更改成了 pk_table_1(主键 Unique) key datetime,cid idx_table_1(索引 Unique) key cid,datetime idx_table_2(索引 Normal) key cid 仍然跟之前的执行计划结果一样。 索引会区分 联合字段的前后顺序吗?我使用 exists的执行计划结果也跟in的一样?
wangwei 2014-10-23
  • 打赏
  • 举报
回复
优化通过计算得出的走idx_table_2是最优的,如果你可以通过提示是优化器走idx_table_1 /* index(表名,索引名) */
不写代码的钦 2014-10-23
  • 打赏
  • 举报
回复
引用 楼主 sm357753 的回复:
我的table表下有 pk_table_1(主键 Unique) key cid,datetime idx_table_1(索引 Unique) key cid,datetime idx_table_2(索引 Normal) key cid 现在 索引1和主键是重复的。 我查询 select * from table datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid in (1,2,3) 时为什么是使用 idx_table_2 索引?
oracle目前采用最优方案,所以肯定走idx_table_2索引比另外两个效率高。 下面说下我对这个现象的理解: 你这个sql句子对于datetime而言是等值查询,对于cid相当于范围查询,而 oracle的联合索引,字段顺序只有是当等值查询在前,范围查询在后效率才高, 使用联合索引才最优。所以你试试idx_table_1(索引 Unique) key cid,datetime 这个索引改成这样idx_table_1(索引 Unique) key datetime,cid,也就是调换索引 列的顺序。(当然如果要看哪种情况查询多一点,如果这个sql只是偶尔执行一次, 那就不要随意改动了。)这样oracle大概就会使用联合索引了。
Gomes 2014-10-23
  • 打赏
  • 举报
回复
引用 1 楼 weiwangsisoftstone 的回复:
你想让优化器优化器走 idx_table_1 而实际却走 idx_table_2 是吗? 你这样写看看执行计划: slect * from table where datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid =1 union slect * from table where datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid =2 union slect * from table where datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid =1 然后在看看这个执行计划,对比一下 slect * from table where datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid in (1,2,3)
是的, 使用 datetime = ‘’ and cid ='1'的话肯定是 走 PK_TABLE_1主键了,但是我后面 in的字符有80十多个,就不能这么一直的union。 我主要想知道,为什么不会走 idx_table_1? in不是也会使用索引的吗?
wangwei 2014-10-23
  • 打赏
  • 举报
回复
你想让优化器优化器走 idx_table_1 而实际却走 idx_table_2 是吗? 你这样写看看执行计划: slect * from table where datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid =1 union slect * from table where datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid =2 union slect * from table where datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid =1 然后在看看这个执行计划,对比一下 slect * from table where datetime = to_date('22-10-2014 21:55:00', 'dd-mm-yyyy hh24:mi:ss') and cid in (1,2,3)
不写代码的钦 2014-10-23
  • 打赏
  • 举报
回复
引用 9 楼 sm357753 的回复:
[quote=引用 7 楼 wildwave 的回复:] datetime字段选择性不高,或者不是date类型。如果非以上,重新采集表的统计信息 另外,并非重复索引,索引!=约束,只不过主键/唯一键是通过索引来实现了,如果创建时不存在对应的索引,则会自动创建
datetime是 date类型。 "另外,并非重复索引,索引!=约束" 谢谢解答,一直就把约束当做索引的使用了。。。[/quote] 7楼DAVE回复很犀利,按照他说得试试。
Gomes 2014-10-23
  • 打赏
  • 举报
回复
引用 7 楼 wildwave 的回复:
datetime字段选择性不高,或者不是date类型。如果非以上,重新采集表的统计信息 另外,并非重复索引,索引!=约束,只不过主键/唯一键是通过索引来实现了,如果创建时不存在对应的索引,则会自动创建
datetime是 date类型。 "另外,并非重复索引,索引!=约束" 谢谢解答,一直就把约束当做索引的使用了。。。
Gomes 2014-10-23
  • 打赏
  • 举报
回复
引用 6 楼 arlen1990 的回复:
第一点。先纠正下,我上面说错了,in()这个相当于等值查询,所以你的语句组合索引顺序和这个句子执行计划 没有关系。 第二点。刚才只是我想象了一下执行计划(因为你具体表中每列的重复率什么的我都不知道), 真正oracle执行计划是按照最优执行的,所以肯定走idx_table_2效率比走另外两个索引效率高, 楼主可以再语句里面加入/*+index(idx_table_1)*/* 让oracle强制走组合索引,综合效率肯定比 idx_table_2低。 第三点。回答你的索引区分前后顺序吗? 回答是肯定要区分的,对于索引两列都是等值查询时候, 前后顺序怎么样效率一样,但是一列为等值,一列为范围,要把等值列放到前面,这样索引效率更高; 但是如果建的组合索引,查询时候只查询组合索引中一列,这时候只查询的这一列必须放在组合索引 前面,要不然组合索引失效,最后执行计划不是index range scan,而是table access full,也就是最后 走的全表扫描。 关于组合索引这一点,我记得梁老师的收获,不止oracle里面有讲,刚才看了下,在书的272页往后有 详细介绍,楼主方便可以去看。我自己组织的语言略显粗糙,作为参考看看就好。
cid和datetime组合是唯一的,所以应该不是重复率的问题吧?所以我也是因为觉得是唯一的,应该走组合索引效率会高点吧? 谢谢你的一直回复。
小灰狼W 2014-10-23
  • 打赏
  • 举报
回复
datetime字段选择性不高,或者不是date类型。如果非以上,重新采集表的统计信息 另外,并非重复索引,索引!=约束,只不过主键/唯一键是通过索引来实现了,如果创建时不存在对应的索引,则会自动创建
不写代码的钦 2014-10-23
  • 打赏
  • 举报
回复
引用 5 楼 sm357753 的回复:
我现在更改成了 pk_table_1(主键 Unique) key datetime,cid idx_table_1(索引 Unique) key cid,datetime idx_table_2(索引 Normal) key cid 仍然跟之前的执行计划结果一样。 索引会区分 联合字段的前后顺序吗?我使用 exists的执行计划结果也跟in的一样?
第一点。先纠正下,我上面说错了,in()这个相当于等值查询,所以你的语句组合索引顺序和这个句子执行计划 没有关系。 第二点。刚才只是我想象了一下执行计划(因为你具体表中每列的重复率什么的我都不知道), 真正oracle执行计划是按照最优执行的,所以肯定走idx_table_2效率比走另外两个索引效率高, 楼主可以再语句里面加入/*+index(idx_table_1)*/* 让oracle强制走组合索引,综合效率肯定比 idx_table_2低。 第三点。回答你的索引区分前后顺序吗? 回答是肯定要区分的,对于索引两列都是等值查询时候, 前后顺序怎么样效率一样,但是一列为等值,一列为范围,要把等值列放到前面,这样索引效率更高; 但是如果建的组合索引,查询时候只查询组合索引中一列,这时候只查询的这一列必须放在组合索引 前面,要不然组合索引失效,最后执行计划不是index range scan,而是table access full,也就是最后 走的全表扫描。 关于组合索引这一点,我记得梁老师的收获,不止oracle里面有讲,刚才看了下,在书的272页往后有 详细介绍,楼主方便可以去看。我自己组织的语言略显粗糙,作为参考看看就好。

17,140

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧