空间与时间的取舍问题,请前辈指教

有这么一张表Temp,数据量在500万左右【无大字段】

对该表频繁操作的SQL:select id from Temp W where userId
                            NOT REGEXP_LIKE(NVL(W.userId , ' '),
                           '(^' || V_userId || '$)|(^' || V_userId || ',)|(,' ||
                           V_userId || '$)|(,' || V_userId || ',)');

假设现可做如下优化:
1. 经过小的逻辑变更后,可将条件改为NOT REGEXP_LIKE(NVL(W.userId , ' '),'\(' || V_userId || '\)'),是否可以提升效率?

2. 如果第1点可以提升效率,但为了提升效率,逻辑做了变更。
   原userid是这么存放的:123,345,456
   变更后的userId存放:(123)(345)(456)
   也就是说比之前多占几个字符,小数据量情况下可能无异,但是当数据量达到上千万时,上述第1点的变更是否还有必要?

学习可能到达钻牛角尖阶段,望各位前辈解惑,非常感谢!
标签: 暂无标签
oracle123

写了 4 篇文章,拥有财富 12,被 1 人关注

转播转播 分享分享 分享淘帖
回复

使用道具

P6 | 发表于 2010-11-6 20:31:08
首先,我要看一条sql语句的性能,就是看这条语句的执行计划。
上面的sql语句的执行计划应该会很差,因为上面的sql语句走不了索引,会造成大量的物理读和逻辑读。可以参考v$segstat等视图去查看。
最直接的就是查看执行计划。
建议:改变表的结构,可以考虑将userid列可以做成三列(具体还要看数值的分布情况),另外,不要在条件列上使用函数,你可以将条件列的数值进行处理,例如加上not null,就可以避免nvl函数。
回复

使用道具

P4 | 发表于 2010-11-8 10:54:38
对LZSQL语句中的变量进行替换v_userid = 'abcd'
select '(^' || 'abcd' || '$)|(^' || 'abcd' || ',)|(,' || 'abcd' || '$)|(,' || 'abcd' || ',)' from dual;
得到结果如下
(^abcd$)|(^abcd,)|(,abcd$)|(,abcd,)
(^abcd$):以abcd开头,以abcd结尾,及abcd本身
(^abcd,):以abcd,开头
(,abcd$):以,abcd结尾
(,abcd,):包含,abcd,
哪么这个SQL语句应该就是使用正则查询包含abcd(v_userid)的记录,这个功能类似like '%%',是用不上索引的,建议LZ使用ORACLE的全文索引;

网上面有很多关于全文检索方面的介绍,这里把自己使用的一些经验共享出来,大家共同学习,如有错误请大家指正;我把创建全文检索的过程封装成了一个存储过程,此存储过程的作用是
1、如果一个表从没有创建过全文检索则开始创建全文检索;
2、如果已经创建了全文检索则对全文检索进行刷新,以使新加入的数据也能检索出来;

使用全文检索的流程如下:
1、添加权限
    检查数据库中是否有CTXSYS用户和CTXAPP角色。如果没有这个用户和角色,意味着你的数据库创建时未安装intermedia功能。你必须修改数据库以安装这项功能。
   把CTXAPP角色赋于当前用户 GRANT CTXAPP TO 当前用户;
   把CTX_DDL的执行权限赋于当前用户; GRANT EXECUTE ON CTX_DDL TO 当前用户;
2、创建中文解析类型;
   在当前用户下执行 EXEC CTX_DDL.CREATE_PREFERENCE('CTX_LEXER','CHINESE_VGRAM_LEXER');
3、创建全文检索字段;
   这里有几个需要注意的地方,也是小弟在使用时摸索出来的,如和ORACLE官方文档中声明的重合,纯属偶然(^o^);一、全文检索字段间最好用“,”隔开,这对汉字的拆分有帮助,如qwjs=王刚,19890622,男......;二、全文检索字段中不要把数字和数字放在一起,中间要用汉字或字母分开,否则检索不出来,如“王刚,19890622,371312,男”,此时使用全文检索查询19890622或371312时检索不出;但如果是“王刚,19890622,男,371312”就没问题了;
4、创建全文检索存储过程
   参考附件
5、创建全文检索方法
   EXEC P_CREATE_QWJS_CN('参数1','参数2','参数3');
    说明:
     参数1:是全文检索的索引名称;参数2:是表名;参数3:是全文索引的字段名如上面例子中的qwjs;
    如:EXEC P_CREATE_QWJS_CN('IDX_CK_QWJS','T_RK_CK','QWJS');
6、全文检索查询方法
   select * from 表名 where contains(qwjs,'检索的值') > 0; 例: select * from t_rk_ck where contains(qwjs,'王刚') > 0,如果是多条件可用select * from t_rk_ck where contains(qwjs,'王刚') > 0 and contains(qwjs,'19890622') > 0,或者是select * from t_rk_ck where contains(qwjs,'王刚 and 19890622') > 0;

参考附件

P_CREATE_QWJS_CN.rar

928 Bytes, 下载次数: 4

回复

使用道具

您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

意见
反馈