1

我有以下运行非常慢的查询(几乎 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 激活 1 const 43072 使用 where;使用文件排序
1 SIMPLE news_categories eq_ref PRIMARY,id PRIMARY 4 news_category_id 1      

我在以下列有索引 news_id(主键) date_online 已激活 category_id

当我查看 EXPLAIN EXTENDED 结果时,我看到了 USING_WHERE; 使用文件排序。我知道他们两个都很糟糕,但我不知道如何解决这个问题。

4

4 回答 4

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
于 2013-03-13T11:37:19.483 回答
1

尝试为date_online(类型 B 树)添加索引。另外,我会尽量避免在 where close 中使用 NOW() ,而是将其设置在变量中并改用该变量。

我想 id 字段是键,所以它们已经被索引了。

于 2013-03-13T11:16:58.733 回答
1

除了其他有价值的建议之外,您还有 DATE(news.date_online)=2013-02-25。这似乎会迫使 MySQL 将 news.date_online 转换为表中每一行的不同格式。这将停止索引有用。

可能将其更改为news.date_online BETWEEN '2013-02-25 00:00:00' AND '2013-02-25 23:59:59'这应该(我认为)允许使用 date_online 上的索引

于 2013-03-13T12:00:26.407 回答
-1

您的查询正在获取特定日期的数据,因此在这种情况下您可以省略该AND news.date_online < NOW()部分(也许查询优化器会为您执行此操作)。

在另一种情况下,如果您想要所有活动新闻而不指定 a date_online,您也应该摆脱 NOW()。问题是,您的查询不能被数据库缓存,因为它包含每次执行都不同的部分( NOW() )。您可以通过在此处提供计算常数来做到这一点。如果您在比较过程中省略了分钟部分,则可以将其缓存为最大值。60 秒。

接下来,您应该为您正在使用的列创建一个多列索引,因为我猜category_id,date_online并且activated几乎用于每个查询。这将使插入速度稍慢一些,但从它的样子(新闻应用程序)来看,读取次数将比插入次数多得多。

于 2013-03-13T11:45:52.530 回答