Question

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.

Was it helpful?

Solution 4

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 activatedare 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.

OTHER TIPS

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top