tags:

views:

140

answers:

6

Can't figure this one out... when I execute a select query it shows an explain plan cost of ~4500 and takes ~3 seconds to return. When I wrap that query (no changes) inside of:

select count(*) from (
 /*query here*/
)

It times out. It's at 5 minutes and counting now.

I tried this in SQL Developer and Aqua Data Studio -- same results.

A: 

It could be that optimizer doesn't "know" what your tables really look like.

Try to analyze the tables that are used in the query:

EXEC dbms_stats.gather_table_stats(
    ownname => <owner-name>,
    tabname => <table-name>,
    cascade => TRUE );
Peter Lang
A: 

It's impossible to tell without seeing your entire query, but for starters, I'd try looking at the explain plan output.

dcp
+4  A: 

When doing COUNT(*), the optimizer changes its goal to ALL_ROWS which may affect the plan severely.

Could you please post your query here?

Quassnoi
I did not realize this would affect the plan... it's actually surprising that it does, since I would expect the original plan to be what it determines the most efficient and the only way to know the count of that resultset is to first execute the nested query.
RenderIn
@RenderIn: your optimizer goal seems to be set to `FIRST_ROWS` (which means return the first records as soon as possible, even if the overall query time will increase). However, Oracle's optimizer is not very smart and can often be confused. BTW, when run your query in `SQL Developer`, do you ever press "Fetch All" to get **all** results?
Quassnoi
@Quassnoi: Not sure exactly where the "Fetch All" is located, but when I execute the script (F5) rather than run the statement (F9) it will return a max of 5000 rows instead of the default 50 when using F9. It took ~11 seconds to return 5k rows at once, and the total is 9520 records.
RenderIn
@RenderIn: could you please post your query and both plans here?
Quassnoi
A: 

The COUNT(*) operation counts all rows fed to it by execution plan branch under it. Meaning that the optimizer waits for ALL_ROWS to return before completing its execution which can severely affect your query plan.

ahsteele
A: 

You want to use a defined select for your count query, the optimized doesn't know what tables it will be counting over.

Also, dont use count(*) as it will be counting across all columns, just use count(COLUMN_NAME)

Glennular
Not true. count(*) count all rows. count(COLUMN_NAME) counts all rows where that column in not null. http://download.oracle.com/docs/cd/E11882_01/server.112/e10592/functions037.htm#SQLRF00624
Todd Pierce
Note: COLUMN_NAME should be an PK or Unique column.
Glennular
A: 

If you are trying to do something like this:

SELECT COUNT(*)
FROM (SELECT...FROM...);

Then you should try specifying what field you wish to perform the count on, for example:

SELECT COUNT(myfield)
FROM (SELECT whatever, whatever, whatever FROM MYTABLE);

Is that what you are referring to?

ajdams
This can change the query semantics: it will only return count of records with `myfield IS NOT NULL`, and has not performance benefit if `myfield` can not be a `NULL`.
Quassnoi
Ah that's true, +1
ajdams