加速 django 中的 mysql 查询/mysql 视图
我使用以下代码从数据库中选择热门新闻条目(按日期):
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;
I use the following code to select popular news entries (by date) from the database:
popular = Entry.objects.filter(type='A', is_public=True).extra(select = {'dpub': 'date(dt_published)'}).order_by('-dpub', '-views', '-dt_written', 'headline')[0:5]
To compare the execution speeds of a normal query and this one I ran the following mysql queries:
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]
As you can see the normal query is much faster. Is there a way to speed this up?
Is it possible to use mysql views with django?
I realize I could just split the datetime field into two fields (date and time), but I'm curious.
Structure:
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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
此查询在
dpub
上订购,而此查询:在
id
上订购。由于
id
很可能是表的PRIMARY KEY
,并且每个PRIMARY KEY
都有一个隐式索引支持它,ORDER BY< /code> 不需要排序。
dpub
是一个计算字段,而MySQL
不支持计算字段上的索引。但是,ORDER BY dt_published
也是一个ORDER BY dpub
。您需要将查询更改为:
并在
news_entry (dt_published)
上创建索引。更新:
由于
DATE
是一个单调函数,您可以使用这个技巧:此查询执行以下操作:
选择第
500
记录dt_published DESC
顺序,或者如果表中的记录少于500
则发布的第一条记录。获取晚于所选最后一条记录的日期发布的所有记录。由于
DATE(x)
始终小于或等于x
,因此可以有超过500
记录,但仍然比整个表少得多。
适当地命令和限制这些记录。
您可能会发现这篇文章很有趣,因为它涵盖了类似的问题:
This query orders on
dpub
, while this one:orders on
id
.Since
id
is most probably aPRIMARY KEY
for your table, and eachPRIMARY KEY
has an implicit index backing it,ORDER BY
does not need to sort.dpub
is a computed field andMySQL
does not support indexes on computed fields. However,ORDER BY dt_published
is anORDER BY dpub
as well.You need to change your query to this:
and create an index on
news_entry (dt_published)
.Update:
Since
DATE
is a monotonic function, you may employ this trick:This query does the following:
Selects the
500th
record indt_published DESC
order, or the first record posted should there be less than500
records in the table.Fetches all records posted later than the date of the last record selected. Since
DATE(x)
is always less or equal tox
, there can be more than500
records, but stillmuch less than the whole table.
Orders and limits these records as appropriate.
You may find this article interesting, since it covers a similar problem:
可能需要
dt_published
上的索引。您能发布这两个查询的查询计划吗?May need an index on
dt_published
. Could you post the query plans for the two queries?