注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

lazydba

hello

 
 
 

日志

 
 

索引和顺序  

2009-06-12 16:34:15|  分类: all about databa |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
像下面这类语句是不会走id上的索引的,因为在id上执行了函数操作。
select *
from t
where func(id) = :1;

这是为什么呢?
我猜是这样的:id 和 func(id)的排序规则可能是不一样的,而索引(B树索引)是基于数据有序这个前提的。也就是从id上的索引来看,fund(id)不一定是有序的,所以不能用索引。

比如id是数字类型的,id上的索引是按数字排序的,数字和字符排序规则不一样,那么to_char(id)=:1就是没法走索引。
1???????????????? 1
2??? ===>?? 12
12?????????????? 123
123????????????? 2
to_char(id) =:1要用像右边那么排序的索引,而不是左边的。数字索引是像左边那样排序的。

那为什么func(id)和id排序规则一样的时候,func(id)=:1还是不能走索引呢?
比如
where id + 0 = :1
where char_id || '' =: 1

可能是为了简化数据库的代码。

那为什么类型不匹配的时候,是在列上执行转换函数,而不是在变量上执行函数呢?
比如
id = char_val 会转换成 to_char(id) = char_val
而不是转换成 id = to_number(char_val)呢?
可能是数据库相信自己的数据,不相信传进来的值?


结论:
虽然可以有很多种不同的方法来做同一件事情,而且不同的方法从逻辑上看是一样的,但是一般还是应该用常规方法。
比如查询就应该写成
select c1 from t where id = to_number(char_val);
更好的方法是程序端保证传的值和数据库的列类型匹配。
不要在id上运算。

毕竟机器不是人。

像下面逻辑上正确的写法也是应该避免的:
select count(*) from a where ... order by c;
select count(distinct id) from a where ...; --这里id是主键
.etc


  评论这张
 
阅读(167)| 评论(1)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017