最近在做一个需求,数据量比较大,遂自己根据查询语句建了几个索引,但是依然发现效果不明显。
让DBA帮忙优化后,指出在查询语句中,关于日期的过滤写法有问题:
T46460.gmv_date = TIMESTAMP '2012-11-01 00:00:00'
应该改成to_date的方式,这样执行起来要快不少。
首先去查了下为什么这种写法就会很慢,我在answer中针对日期列指定了具体的日期,比如2012年11月1日,以生成查询sql,BIEE在生成查询sql的时候,会用timestamp的方式进行转换,但是这样就会跳过该列的索引了,导致相当于进行了全表扫描来着。
另外的一个现象:
在查询提示器里,选择日期,一开始没有时分秒,一旦选择了执行后,查询提示器里会自动的加上了时分秒。
所以解决方案是,如何在生成的查询sql里保证使用的是to_date函数即可。
网上老外的博客里提到了针对timestamp列建立索引的方式来优化查询。
链接如下:http://obiee101.blogspot.com/2009/03/obiee-date-timestamp-and-oracle-indexes.html
遇到类似问题的文章链接:
http://www.rittmanmead.com/2009/03/dates-timestamp-and-oracle-bi-answers-filters/
数据平台的同事的文章:
http://www.alidata.org/archives/107
经过检查,rpd中针对日期维度使用的数据类型为datetime,于是修改成date类型。
这样改好后,的确查询的语句使用了to_date函数,查询性能提升明显。
但是发布后,却引入了新的问题。
发现默认展示没有问题,针对报表进行日期选择查询后,报如下错误:
经过上网查询资料,说是BIEE的一个bug,patch的说明如下:
http://obiee101.blogspot.com/2010/01/obiee-patches-101341-part-2.html
在网上搜索其他文章,
https://forums.oracle.com/forums/thread.jspa?messageID=10684745
http://blog.csdn.net/mlz_2/article/details/6154805
可以通过修改globalfilterprompt.js文件解决。该文件的路径为:
OracleBI\oc4j_bi\j2ee\home\applications\analytics\analytics\res\b_mozilla\prompts\globalfilterprompt.js
我用firebug进行了debug,该文件的230多行,
var sTimeZoneOffset = tArgs[3];
var nOffset = parseInt(sTimeZoneOffset) if (nOffset) { var tDTP = new DateTimeParser(); for (var i = 0; i < tValues.length; ++i) { tValues[i] = saw.tz.parseAndAdjustTimeZoneOffset(tValues[i], nOffset); } }
在for循环里面,parseAndAdjustTimeZoneOffset方法返回后,值就变成了日期+时分秒的格式。
该方法是在OracleBI\oc4j_bi\j2ee\home\applications\analytics\analytics\res\b_mozilla\common\datetime.js文件里,873行左右。
saw.tz.parseAndAdjustTimeZoneOffset = function (sDateTime, nTimeZoneOffset) { if (sDateTime) { if (nTimeZoneOffset) { var tDTP = new DateTimeParser(); var tDateTime = tDTP.parse(sDateTime, 1 | 2 | 4 | 8 | 16 | 32); if (tDateTime) { tDateTime.adjustTimeZoneOffset(nTimeZoneOffset); var sValue = tDateTime.dateString() + ' ' + tDateTime.timeString(); return sValue; } } } return sDateTime; }
显式的加上了时分秒,因为上述的文章里没有具体讲到如何去更改,所以我就尝试将
tValues[i] = saw.tz.parseAndAdjustTimeZoneOffset(tValues[i], nOffset);
的调用给干掉。重新测试后,发现问题并未解决。估计js改的不彻底。
后续想到,其实我的本地OBIEE环境并没有遇到这个类似的问题。既然oracle已经打了patch,估计是我们的BIEE版本比线上的BIEE版本要新(事实上也正是如此)。
于是也不纠结js具体如何改了,把线上的js文件和我本地的js文件了进行了对比,发现的确是有差异来着。
于是将本地的js文件替换掉线上的js文件,最终问题解决。
补充下,记得清浏览器的缓存,否则浏览器加载的还是老的js,这个就坑爹了。
There is one last thing you need to know before proceeding – the browser caches the JS files so you’ll need to clear the browser’s cache every time you change your code. In Internet Explorer, you can do it in Tools -> Internet Options -> Delete Files -> Delete all offline content. You’ll do it a lot while developing, so having a button that does that will be great. You can use Microsoft’s IE developer toolbar or another developer toolbar.