SELECT
b.categoryid,
SUM(viewcount) AS cnt,
categoryname
FROM
bookvisit AS bv
INNER JOIN book AS b ON b.isbn = bv.isbn
LEFT JOIN category AS c ON b.categoryid = c.categoryid
WHERE
b.categoryid IS NOT NULL AND
b.categoryid <> 0
GROUP BY
b.categoryid
ORDER BY
cnt DESC,
bv.isbn
LIMIT 0, 4
I have three tables –
book (contains books information)
bookvisit (book visit info)
category (category master )
What I need is popular categories, above query is fine with two eq_ref but it has a
Using temporary; Using filesort also
any help ?
As @dj_segfault said, you cannot have an index on an aggregate column in
MySQLand you will have to write a service that would cache the SUMs in a shapshot table (which you can index).Here’s how you can do it and still have the accurate statistics:
Create a snapshot table:
with a
PRIMARY KEYoncategory.Create a single-field, single-record table called
snapshot_time:On a timely basis, fill this table with the query:
Create the following indexes:
Run this query:
The query will return you accurate visit count.
The main idea is that you need to scan only the records in
bookvisitthat were collected after the statistics were cached.More than that: you don’t even have to scan all records in the cached statistics. Since the number of visits only grows, you can only scan the results that can possibly get into the first four.
If the
4threcord has1,000,000page views in the snapshot, and1,000page views happened after you took the snapshot, you can only select the records from the snapshot withcnt >= 999,000. The other records could not theoretically hit this limit, since it would take more than1Kpage views.The only problem is that you can delete the books or change their categories. In this case you would just need to recalculate the statistics or fall back to your original method.