تسريع استعلامات mysql / وجهات نظر mysql في Django
-
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 إلى حقلين (التاريخ والوقت) ، لكنني فضولي.
بنية:
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
. هل يمكنك نشر خطط الاستعلام للاستفسارات؟