Dynamic query with HibernateCritera API & Oracle - performance

匆匆过客 提交于 2019-12-02 07:29:20

There are a couple of things here. First of all, you cannot bind an IN list, at least I am pretty sure you cannot. I suspect Hibernate is using some sort of trick you put your array contents into a static inlist Oracle can use.

Secondly if this query is executed with lots of different parameters, you must you bind variables or the performance of the entire database will suffer.

That said, there is a way to bind an IN list using a 'trick' which Tom Kyte describes on his blog -

http://tkyte.blogspot.com/2006/01/how-can-i.html

The code in there looks like:

ops$tkyte@ORA10GR2> with bound_inlist
2  as
3  (
4  select
5    substr(txt,
6           instr (txt, ',', 1, level  ) + 1,
7           instr (txt, ',', 1, level+1) - instr (txt, ',', 1, level) -1 )
8           as token
9    from (select ','||:txt||',' txt from dual)
10  connect by level <= length(:txt)-length(replace(:txt,',',''))+1
11  )
12  select *
13    from all_users
14   where user_id in (select * from bound_inlist);

USERNAME                          USER_ID CREATED
------------------------------ ---------- ---------
SYSTEM                                  5 30-JUN-05
OPS$TKYTE                             104 20-JAN-06

The part:

12  select *
13    from all_users
14   where user_id in (select * from bound_inlist);

Is basically where your query goes. The bit above is the trick which splits the comma separated string into a list of values. Instead of binding a list into the :txt placeholder, you would need to convert the list to a string and just bind that.

Are you sure the difference in query times isn't due to caching or load variations on the machine? Parsing the query will take a little time, but several seconds is a long time.

I've worked with IN(...) queries that had up to a 1000 of ids in that list; I can guarantee you that it does not take several seconds to parse / prepare / cache a statement.

Hibernate does indeed auto-expand the parameter list you specify using the actual number of elements in the list you pass, so if you really wanted to keep it "fixed" at a certain level all you need to do is to append enough -1s to the end. However, this is most certainly not the problem especially since we're talking about speeding up the first query run - no statements have been prepared / cached yet anyway.

Did you look at the execution plans for your queries? Both via explain plan and autotrace enabled? Do they differ when you have 30 elements and 120 elements in your list? Does your actual query really look like "select ... from table where id in (...)" you've posted or is it more complex? I'm willing to bet that somewhere between 30 and 120 elements Oracle decides (perhaps mistakenly) that it'll be faster not to use an index, which is why you're seeing the time increase.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!