加速django中的mysql查询/ mysql视图

时间:2010-09-07 12:56:47

标签: mysql django django-models query-optimization sql-view

我使用以下代码从数据库中选择热门新闻条目(按日期):

popular = Entry.objects.filter(type='A', is_public=True).extra(select = {'dpub': 'date(dt_published)'}).order_by('-dpub', '-views', '-dt_written', 'headline')[0:5]

为了比较普通查询和这个查询的执行速度,我运行了以下mysql查询:

SELECT *, date(dt_published) as dpub FROM `news_entry` order by dpub DESC LIMIT 500

# Showing rows 0 - 29 (500 total, Query took 0.1386 sec)

-

SELECT * , DATE( dt_published ) AS dpub FROM  `news_entry` ORDER BY id DESC LIMIT 500

# Showing rows 0 - 29 (500 total, Query took 0.0021 sec) [id: 58079 - 57580]

正如您所看到的,正常查询要快得多。有没有办法加快速度呢?

是否可以在django中使用mysql视图?

我意识到我可以将日期时间字段分成两个字段(日期和时间),但我很好奇。


结构:

CREATE TABLE IF NOT EXISTS `news_entry` (
  `id` int(11) NOT NULL DEFAULT '0',
  `views` int(11) NOT NULL,
  `user_views` int(11) NOT NULL,
  `old_id` int(11) DEFAULT NULL,
  `type` varchar(1) NOT NULL,
  `headline` varchar(256) NOT NULL,
  `subheadline` varchar(256) NOT NULL,
  `slug` varchar(50) NOT NULL,
  `category_id` int(11) DEFAULT NULL,
  `is_public` tinyint(1) NOT NULL,
  `is_featured` tinyint(1) NOT NULL,
  `dt_written` datetime DEFAULT NULL,
  `dt_modified` datetime DEFAULT NULL,
  `dt_published` datetime DEFAULT NULL,
  `author_id` int(11) DEFAULT NULL,
  `author_alt` varchar(256) NOT NULL,
  `email_alt` varchar(256) NOT NULL,
  `tags` varchar(255) NOT NULL,
  `content` longtext NOT NULL
) ENGINE=MyISAM DEFAULT;

2 个答案:

答案 0 :(得分:2)

SELECT *, date(dt_published) as dpub FROM `news_entry` order by dpub DESC LIMIT 500

此查询在dpub上排序,而这一个:

SELECT * , DATE( dt_published ) AS dpub FROM  `news_entry` ORDER BY id DESC LIMIT 500

id上的订单。

由于id很可能是您的表的PRIMARY KEY,并且每个PRIMARY KEY都有一个支持它的隐式索引,ORDER BY不需要排序。

dpub是计算字段,MySQL不支持计算字段的索引。但是,ORDER BY dt_published也是ORDER BY dpub

您需要将查询更改为:

SELECT *, date(dt_published) as dpub FROM `news_entry` order by date_published DESC LIMIT 500

并在news_entry (dt_published)上创建索引。

<强>更新

由于DATE是一种单调函数,你可以使用这个技巧:

SELECT  *, DATE(dt_published) AS dpub
FROM    news_entry
WHERE   dt_published >=
        (
        SELECT  md
        FROM    (
                SELECT  DATE(dt_published) AS md
                FROM    news_entry
                ORDER BY
                        dt_published DESC
                LIMIT 499, 1
                ) q
        UNION ALL
        SELECT  DATE(MIN(dt_published))
        FROM    news_entry
        LIMIT 1
        )
ORDER BY
        dpub DESC, views DESC, dt_written DESC, headline
LIMIT 500

此查询执行以下操作:

  • 选择500th订单中的dt_published DESC记录,或者如果表中的记录少于500,则会发布第一条记录。

  • 获取所有在所选最后一条记录的日期之后发布的记录。由于DATE(x)始终小于或等于x,因此可能会有超过500个记录,但仍然 比整张桌子要少得多。

  • 根据需要对这些记录进行排序和限制。

您可能会发现这篇文章很有趣,因为它涵盖了类似的问题:

答案 1 :(得分:0)

可能需要dt_published上的索引。你能发布两个查询的查询计划吗?