我有以下查询,运行速度很慢(差不多50000条记录)
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
我有MySQL客户端版本5.0.96
当我使用此查询运行EXPLAIN EXTENDED调用时,结果如下:
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
我有以下列的索引 news_id(主键) date_online 活性 CATEGORY_ID
当我查看EXPLAIN EXTENDED结果时,我看到了USING_WHERE;使用FILESORT。我知道它们都很糟糕,但我不知道如何解决这个问题。
答案 0 :(得分:1)
尝试为date_online
添加索引(类型B-tree)。另外,我会尽量避免在关闭时使用NOW(),而是将其设置在变量中,而是使用变量。
我认为id字段是键,因此它们已被索引。
答案 1 :(得分:1)
使用LEFT JOIN并查看差异
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
答案 2 :(得分:1)
除了其他有价值的建议,你还有DATE(news.date_online)= 2013-02-25。这似乎迫使MySQL将news.date_online转换为表格中每一行的不同格式。这将阻止索引有用。
可能会将其更改为 news.date_online BETWEEN'2013-02-25 00:00:00'和'2013-02-25 23:59:59'应该(我认为)允许要使用的date_online上的索引
答案 3 :(得分:-1)
您的查询是获取特定日期的数据,因此在这种情况下您可以省略AND news.date_online < NOW()
部分(也许查询优化程序会为您执行此操作)。
在另一种情况下,如果你想要所有活跃的新闻而不指定date_online
,你也应该摆脱NOW()。问题是,数据库无法缓存您的查询,因为它包含每次执行不同的部分(NOW())。您可以通过在那里提供计算常数来实现此目的。如果省略比较期间的分钟部分,则可以缓存最大值。 60秒。
接下来,您应该为正在使用的列创建多列索引,因为我猜几乎每个查询都使用category_id
,date_online
和activated
。这会使插入变慢一些,但从它的外观看(新闻应用程序),读取的内容会比插入更多。