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]
ご覧のとおり、通常のクエリははるかに高速です。これをスピードアップする方法はありますか?
MySQLビューをDjangoで使用することは可能ですか?
DateTimeフィールドを2つのフィールド(日付と時刻)に分割できることに気付きましたが、興味があります。
構造:
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
おそらくaです 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
. 。 2つのクエリのクエリ計画を投稿できますか?