这种SQL如何建索引,才能使得其走索引?

[复制链接]
查看11 | 回复9 | 2012-6-15 18:46:55 | 显示全部楼层 |阅读模式
本帖最后由 278676125 于 2013-10-25 21:50 编辑
建测试表:
create table emp_test as select to_char(empno,'00009999') eno,ename from emp t;
加主键:
ALTER TABLE emp_test ADD PRIMARY KEY (eno);
收集统计信息:
begin
dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'EMP_TEST');
end;
/
这样子是走索引的:
21:39:38 SCOTT@orcl> select * from emp_test where eno>='7900';
已用时间:00: 00: 00.00
执行计划
----------------------------------------------------------
Plan hash value: 1122673765
--------------------------------------------------------------------------------------------
| Id| Operation
| Name | Rows| Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT
|
| 1 |16 | 2 (0)| 00:00:01 |
| 1 |TABLE ACCESS BY INDEX ROWID| EMP_TEST | 1 |16 | 2 (0)| 00:00:01 |
|*2 | INDEX RANGE SCAN
| SYS_C0017539 | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ENO">='7900')复制代码
但是我们应用上的SQL是这样的: select * from emp_test where eno>=LPAD('7900',LENGTH(eno),'0');
这样就不走索引了
21:39:47 SCOTT@orcl> select * from emp_test where eno>=LPAD('7900',LENGTH(eno),'0');
已用时间:00: 00: 00.01
执行计划
----------------------------------------------------------
Plan hash value: 3124080142
------------------------------------------------------------------------------
| Id| Operation | Name | Rows| Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT|
| 1 |16 | 3 (0)| 00:00:01 |
|*1 |TABLE ACCESS FULL| EMP_TEST | 1 |16 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ENO">=LPAD('7900',LENGTH("ENO"),'0'))复制代码
我试过建LENGTH(eno)的函数索引,但是发现也不走,想建LPAD函数索引,但是不知道咋建,求大神支招。

回复

使用道具 举报

千问 | 2012-6-15 18:46:55 | 显示全部楼层
直接将where条件做索引 eno>=LPAD('7900',LENGTH(eno),'0')

需要用case when转换一下
回复

使用道具 举报

千问 | 2012-6-15 18:46:55 | 显示全部楼层
这里建LPAD索引对你的查询没有任何帮助
回复

使用道具 举报

千问 | 2012-6-15 18:46:55 | 显示全部楼层
皇家救星 发表于 2013-10-25 21:54
直接将where条件做索引 eno>=LPAD('7900',LENGTH(eno),'0')

请教如何建?'7900'是一个变量
回复

使用道具 举报

千问 | 2012-6-15 18:46:55 | 显示全部楼层
本帖最后由 udfrog 于 2013-10-25 22:02 编辑
为什么要补0,字符串的比较本来就是按位置比较ascii值,既然eno代表数字,那不补肯定不会影响逻辑
回复

使用道具 举报

千问 | 2012-6-15 18:46:55 | 显示全部楼层
因为对LENGTH(eno)进行函数运算了,必须改写之
回复

使用道具 举报

千问 | 2012-6-15 18:46:55 | 显示全部楼层
278676125 发表于 2013-10-25 21:55
请教如何建?'7900'是一个变量

如果是变量那就不好办了
还有什么情况你是没说清楚的,别到时大家帮你想出解决方案,你又冒出一个新条件
回复

使用道具 举报

千问 | 2012-6-15 18:46:55 | 显示全部楼层
eno是不定长的?
这个条件等于TO_NUMBER(eno)>=7900
建个函数索引。
假设你eno全是数字。

回复

使用道具 举报

千问 | 2012-6-15 18:46:55 | 显示全部楼层
newkid 发表于 2013-10-25 23:38
eno是不定长的?
这个条件等于TO_NUMBER(eno)>=7900
建个函数索引。

7900是变量 见4楼
回复

使用道具 举报

千问 | 2012-6-15 18:46:55 | 显示全部楼层
皇家救星 发表于 2013-10-26 00:21
7900是变量 见4楼

我知道是变量,这和我说的有什么关系?
楼主的查询说明他们的eno是不定长的,有 '0008000','03000'这样的数据。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行