在Django中加快MySQL查询 / MySQL的视图
-
01-10-2019 - |
题
我使用以下代码从数据库中选择流行的新闻条目(按日期):
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视图?
我意识到我可以将DateTime字段分为两个字段(日期和时间),但我很好奇。
结构:
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;
解决方案
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
记录,但仍然比整个桌子少得多。订单和限制这些记录。
您可能会发现这篇文章很有趣,因为它涵盖了一个类似的问题:
其他提示
可能需要索引 dt_published
. 。您可以发布两个查询的查询计划吗?
不隶属于 StackOverflow