views:

147

answers:

5

This statement appears inefficient because only one one out of 10 records are selected and only 1 of 100 entries contain comments.

What can I do to improve it ?

$query = "SELECT 
A,B,C,  
(SELECT COUNT(*)
    FROM comments
    WHERE comments.nid = header_file.nid) 
    as my_comment_count
FROM  header_file
Where A = 'admin' "

edit: I want header records even if no comments are found.

A: 

You can try to use a Left Join, this could allow better optimization:

Select a, b, c, Count(*) As my_comment_count
From header_file h
Left Outer Join comments c On ( c.nid = h.nid )
Group By a, b, c
Where A = 'admin'
Peter Lang
Looks cleaner but not sure if any performance gain here. Also I want to include record even if comment count is zero. I would prefer to dig into comment file only if I get a match on where clause.
ernie
I use a `Left Join`, so you get all rows of `header_file`, also those without comments. Your current solution makes sure that comments are only read for those headers matched in `Where`-clause. With my solution the optimizer will decide which way is better.
Peter Lang
+1  A: 

You can add index on a A and nid column.

Svisstack
gos without saying, but I doubled checked.
ernie
When you're dealing with tough programming problems, nothing "goes without saying."
Andy Lester
+1  A: 

I am using an inner join here because it sounds like you only want header_file records that contain comments. If this is not the case, change it to a left outer join:

select h.a, h.b, h.c, c.Count
from header_file h
inner join (
    select nid, count(*) as Count
    from comments
    group by nid
) c on c.nid = h.nid
where h.a = 'admin'
RedFilter
Yes, I want header, regardless of comments so "left outer join" is more appropriate.
ernie
I has seen use of temporary file or "with" clause. Maybe that would be more appropriate here.
ernie
A: 

Insert the comment count number directly in the table, count(*) isn't very efficient.

http://www.mysqlperformanceblog.com/2006/12/01/count-for-innodb-tables/

Telos
@Telos: Read that link carefully, it talks about `SELECT COUNT(*)` being slow when selecting without `WHERE`-clause. This does not apply in the current case, index can and will be used.
Peter Lang
I just found this syntax in http://www.selikoff.net/2008/12/10/memo-avoid-nested-queries-in-mysql-at-all-costs/ . Trying to make it work for me.SET X = CallDatabase("SELECT DISTINCT widgetId FROM widgetOrders");CallDatabase("SELECT id,name,price FROM widgets WHERE id IN ("+X+")");
ernie
+1  A: 

From question:

This statement appears inefficient ...

How do you know it is inefficient?
Do you have execution plan?
Did you measure execution times?
Are you sure it uses index?
You commented Peter Lang's answer: ... not sure if any performance gain here - is based on what?

Basic thing you should know about query execution:

  • Most modern RDBMS-s have query optimizer that analyzes your SQL and determines optimal execution plan.

Your feeling that some query is "bad" doesn't mean anything. You need to check execution plan and then you see if there is anything you can do to improve performance.

For MySql, see article: 7.2.1. Optimizing Queries with EXPLAIN

You could also run SQL from answers and compare execution plans to see if any of proposed solution gives better performance.

zendar
thanks for realilty check. Here is mysql explain.http://tinyurl.com/26bxbq8 Query is actually a bit more complicated than my example above and only have limited test data for now. I see there are also more indexes to add.
ernie