I have the following query which runs very slow (almost 50000 records)
SELECT
news.id,
news.title,
DATE_FORMAT(news.date_online,'%d %m %Y')AS newsNL_Date
news_categories.parent_id
FROM
news,
news_categories
WHERE
DATE(news.date_online)=2013-02-25
AND news.category_id = news_categories.id
AND news.date_online < NOW()
AND news.activated ='t'
ORDER BY
news.date_online DESC
I have MySQL client version 5.0.96
When I run a EXPLAIN EXTENDED call with this query, this is the result:
id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE news ref category_id,date_online,activated activated 1 const 43072 Using where; Using filesort 1 SIMPLE news_categories eq_ref PRIMARY,id PRIMARY 4 news_category_id 1
I have an index on the following columns news_id (primary key) date_online activated category_id
When I look at the EXPLAIN EXTENDED result, I see USING_WHERE; USING FILESORT. I know both of them are bad, but I don't know how to fix this.
Try adding indexes for date_online
(type B-tree). Also I would try to avoid using NOW() in the where close rather set it in a variable and use the variable instead.
I suppose the the id fields are keys so they are already indexed.
Use a LEFT JOIN and see the difference
SELECT
news.id,
news.title,
DATE_FORMAT(news.date_online,'%d %m %Y')AS newsNL_Date
news_categories.parent_id
FROM
news
LEFT JOIN news_categories ON news_categories.id = news.category_id
WHERE
DATE(news.date_online)= '2013-02-25'
AND DATE(news.date_online) < DATE(NOW())
AND news.activated ='t'
ORDER BY
news.date_online DESC
Further to the other worthwhile suggestions, you have DATE(news.date_online)=2013-02-25. This would seem to force MySQL to convert news.date_online to a different format for every row on the table. This will stop the indexes being useful.
Possibly change it to news.date_online BETWEEN '2013-02-25 00:00:00' AND '2013-02-25 23:59:59' which should (I think) allow the index on date_online to be used
Your query is getting data for a specific day, so in this case you can omit the AND news.date_online < NOW()
part (Maybe the query optimizer does this for you).
In the other case, where you want all active news without specifying a date_online
, you also should get rid of the NOW(). The problem is, that your query cannot be cached by the database, because it contains parts ( NOW() ) that are different for every execution. You can do this by providing a calculated constant there. If you omit let's say the minute part during comparison, it can be cached for max. 60 seconds.
Next, you should create a multi-column index for the columns that you are using, because I guess category_id
, date_online
and activated
are used in almost every query. This will make inserts a little slower, but from what it looks like (news application) there will be much more reads than inserts.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.