I know you said this was a translation of your original query. Assuming 
that it is a faithful translation, I have the following suggestions:

Do not enclose numbers with quotes (category_id is a number, right? No 
quotes are needed)

You do not need include the table "category" in this query. You select no 
data from it and refer to it only using it's category_id. That value you 
already have on the "thread_link" table so you do not need any other 
tables to be able to use it.

Rev 1:

SELECT 
        Count(TP.thread_ID) as num_posts
        , Max(TP.post_date) as latest_date
        , T.thread_ID
        , T.thread_name
        , i.post_image
FROM thread as T
INNER JOIN thread_link as TL
        ON TL.thread_id = t.thread_id
        AND TL.category_id = 8759
INNER JOIN thread_post as TP
        ON TP.thread_id = t.thread_id
        AND tp.rating > 0
INNER JOIN thread_image as i
        ON i.thread_id = T.thread_id
        AND i.display_type = 'thumbnail'

You need the count of # of posts and the latest date based on the Thread 
ID, and you know which threads to aggregate based on the category it's in. 
So, you could start by collecting into a temp table only the basic 
information you need for your report. This minimizes the size of the 
intermediate tables so that the GROUP BY  can go much faster.   Then join 
to your temp table any other tables that you need in order to fill in the 
rest of your columns

Rev 2:

CREATE TEMPORARY TABLE tmpStats (KEY(thread_id))
SELECT 
        TP.thread_ID
        Count(TP.thread_ID) as num_posts
        , Max(TP.post_date) as latest_date
FROM thread_posts as TP
INNER JOIN thread_link TL
        ON TP.thread_id = TL.thread_id
WHERE 
        TL.category_ID = 8759
GROUP BY 1
ORDER BY 2,3 DESC;

SELECT ts.num_posts, ts.latest_date, ts.thread_id, t.thread_name, 
i.post_image
FROM tmpStats ts
INNER JOIN thread t
        on t.thread_id = ts.thread_id
INNER JOIN thread_image i
        on i.thread_id = ts.thread_id;

drop table tmpStats;

You get the same results as the "all-in-one" query  but by breaking it 
into smaller steps, you save the engine a "metric butt-load" (trust me, 
it's a rather large unit of measure) of intermediate processing. Just the 
difference in joining 20  records (and not the entire thread_posts table) 
to the thread and thread_image tables  will save you several seconds.

Shawn Green
Database Administrator
Unimin Corporation - Spruce Pine



[EMAIL PROTECTED] wrote on 09/09/2004 11:36:18 AM:

> I'm having a bit of a problem with a query that takes a very long 
> time (up to 1 minute) when many matching rows are found.
> The tables are all indexed and the explain seems to indicate that 
> mysql is using the indexes but it is still painfully slow:
> 
> mysql> SELECT COUNT(TP.thread_id) AS num_posts, MAX(TP.post_date) AS
> latest_date,T.thread_id, T.thread_name, i.post_image
> FROM category AS C
>     -> INNER JOIN thread_link AS TL USE INDEX(CAT_INDEX) ON C.
> category_id = TL.category_id 
>     -> INNER JOIN thread AS T ON TL.thread_id = T.thread_id
>     -> INNER JOIN thread_image AS i ON TL.thread_id = i.thread_id
>     -> INNER JOIN thread_post AS TP USE INDEX(thread_id) ON TL.
> thread_id = TP.thread_id
>     -> WHERE C.category_id =  '8759'  AND i.display_type = 
> 'thumbnail' AND TP.rating > 0
>     -> GROUP  BY TL.thread_id
>     -> ORDER  BY  'num_posts' DESC 
>     -> LIMIT 0 , 20;
> 
> ... results ...
> 20 rows in set (37.37 sec)
> 
> The above query is a hypothetical query (hint: I'm not doing a forum
> db) but it pretty much matches what I'm doing. 
> In this case there are many categories 'C' and a thread 'T' can be 
> in multiple categories that link together with a thread_link 'TL'. 
> Thread posts 'TP' contain the individual posts within a thread topic.
> 
> I want to select the top 20 thread topics 'T', for a particular 
> category based on the number of posts within that thread 'TP'.  I 
> also want to calculate the latest post date (when the last post was 
added).
> 
> The tables work fine, the results are fine... it just ISN'T FAST! 
> Especially if there are a lot of threads for that particular category.
> 
> Here is the explain data:
> +-------+--------+---------------+------------+---------
> +---------------------+------+---------------------------------+
> | table | type   | possible_keys | key        | key_len | ref 
> | rows | Extra                           |
> +-------+--------+---------------+------------+---------
> +---------------------+------+---------------------------------+
> | C     | const  | PRIMARY       | PRIMARY    |       4 | const 
> |    1 | Using temporary; Using filesort |
> | TL    | ref    | CAT_INDEX     | CAT_INDEX  |       4 | const 
> |  105 | Using where                     |
> | T     | eq_ref | PRIMARY       | PRIMARY    |       4 | TL.
> product_id       |    1 |                                 |
> | i     | eq_ref | PRIMARY       | PRIMARY    |       5 | TL.
> thread_id,const |    1 | Using where                     |
> | TP    | ref    | thread_id    | thread_id |       4 | TL.thread_id
> |    2 | Using where                     |
> +-------+--------+---------------+------------+---------
> +---------------------+------+---------------------------------+
> 5 rows in set (0.00 sec)
> 
> I think the problem may be with 'Using Temporary; Using Filesort' 
> probably due to the GROUP BY???
> 
> Here are the indexes:
> thread: 
> - thread_id (PK)
> 
> thread_link: 
> - thread_id, category_id (combined PK)
> - category_id (CAT_INDEX)
> 
> thread_post:
> - thread_id, post_id (combined PK)
> 
> category:
> - category_id
> 
> thread_image:
> - thread_id,display_type (combined PK)
> - thread_id (INDEX)
> 
> Major kudos to whom ever can help me out with this!!
> - John
> 
> -- 
> MySQL General Mailing List
> For list archives: http://lists.mysql.com/mysql
> To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]
> 

Reply via email to