سؤال

أستخدم الكود التالي لتحديد إدخالات الأخبار الشائعة (حسب التاريخ) من قاعدة البيانات:

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. هل يمكنك نشر خطط الاستعلام للاستفسارات؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top