Dave Carabetta wrote:
> 
> Gladly. Note that I have marked with a double-dash (--) where the query is 
> choking and where it ends. Again, if I remove the cfqueryparam, even on just 
> one of the two conditions (doesn't matter which), the query works fine. It's 
> when both are cfqueryparam'ed that it takes forever:
> 
> WHERE p.msa = <cfqueryparam value="#client.msa#" cfsqltype="CF_SQL_CHAR" 
> maxlength="2">
> AND p.sector = <cfqueryparam value="#client.sector#" cfsqltype="CF_SQL_CHAR" 
> maxlength="3">
> AND p.id = pd.id
> -- The next two conditions are where CF chokes when using cfqueryparam
> AND p.x_long >= <cfqueryparam value="#Subj.Long#" 
> cfsqltype="CF_SQL_NUMERIC">
> AND p.y_lat >= <cfqueryparam value="#Subj.Lat#" cfsqltype="CF_SQL_NUMERIC">
> -- End Choke
> AND ((p.x_long != <cfqueryparam value="#Subj.Long#" 
> cfsqltype="CF_SQL_NUMERIC">) OR (p.y_lat != <cfqueryparam value="#Subj.Lat#" 
> cfsqltype="CF_SQL_NUMERIC">))
> ORDER BY dist

That might explain a lot :)

Inside a database server a query undergoes 3 stages (some say 2, but for 
the purpose of this explanation I'm not going to bother about that).

First stage is a rewrite.
Views used in the query are merged with rules/instead of triggers, case 
is corrected etc. to determine what the user actually wants. This stage 
also checks for permissions. So performing the query
SELECT * FROM view1 WHERE ID > 16
on the view  view1 is not what really happens. view 1 is actually:
CREATE VIEW view1 AS SELECT * FROM table1 WHERE somefield = TRUE
So the result is rewritten to become
SELECT * FROM table1 WHERE somefield = TRUE and ID > 16

Second stage is determining the query plan.
The query plan is what is actually going to happen in the database. In 
this case, the optimizer looks at the query, decides that although the 
ID field is indexed it shouldn't use the index because only 15 of the 
1000 rows will not be returned. The database decides it is best to do a 
sequential scan of the entire table1.

Third stage is performing the actual query.
This can be longest part of a query execution if the query is 
complicated, many rows, needs to be sorted. But if it is just one lookup 
it can be extremely fast as well.

What happens is that at the end of stage 2 the database caches the 
resulting query plan together with the result of stage 1.
Next query comes and at the end of stage 1 the database look in the 
cache to see if the execution plan is already there. Needless to say 
that is not often the case (or you would have cached the queryu already 
in CF) because ID is always different.

Here come the bind variables. By using bind variables the database knows 
on beforehand the datatype of the variable. So it can choose to cache 
the execution plan based on the datatype instead of the value. If at 
that point the only thing that is not a database identifier (column, 
table etc.) of some kind is a bind variable, the query will use the 
stored version of the query.

Quite smart, because at every single time you are only getting a single 
record that should be found pretty fast using an index. But once you 
start using < and > the equation changes. Imagine 1000 equally 
distributed records with ID's running from 1 to 1000 and an index on the 
ID column and the folowing queries:
SELECT * FROM table1 WHERE ID > 990
SELECT * FROM table1 WHERE ID > 10

Difference between both is the threshold value for ID. So it would be an 
ideal candidate for bind variables from that angle. But if you look at 
the actual query plan you want, it is not. In the first case you want an 
index scan and then return the 1% accurate records, in the second case 
you want a sequential scan from which you drop the inaccurate records.

This tension between inequality operators and bind variables is probably 
causing your problem.

I just invented this reasoning here since I am a little creative on the 
alcohol here :) But it sure sounds good. And it will probably spark 
enough debate to get to the answer ;)

Jochem
______________________________________________________________________
Dedicated Windows 2000 Server
  PIII 800 / 256 MB RAM / 40 GB HD / 20 GB MO/XFER
  Instant Activation · $99/Month · Free Setup
  http://www.pennyhost.com/redirect.cfm?adcode=coldfusiona
FAQ: http://www.thenetprofits.co.uk/coldfusion/faq
Archives: http://www.mail-archive.com/cf-talk@houseoffusion.com/
Unsubscribe: http://www.houseoffusion.com/index.cfm?sidebar=lists

Reply via email to