Frage

Ich verwende den folgenden Code gelesene Nachrichten Einträge auszuwählen (nach Datum) aus der Datenbank:

popular = Entry.objects.filter(type='A', is_public=True).extra(select = {'dpub': 'date(dt_published)'}).order_by('-dpub', '-views', '-dt_written', 'headline')[0:5]

Um die Ausführungsgeschwindigkeit eines normalen Abfrage zu vergleichen und diese habe ich die folgenden MySQL-Abfragen lautete:

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]

Wie Sie die normale Abfrage sehen können, ist viel schneller. Gibt es eine Möglichkeit, diese zu beschleunigen?

Ist es möglich, mysql Ansichten mit django?

zu verwenden,

Ich weiß, ich nur das Datetime-Feld in zwei Felder (Datum und Uhrzeit) aufgeteilt könnte, aber ich bin neugierig.


Struktur:

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;
War es hilfreich?

Lösung

SELECT *, date(dt_published) as dpub FROM `news_entry` order by dpub DESC LIMIT 500

Diese Abfrage Auftrag dpub, während diese:

SELECT * , DATE( dt_published ) AS dpub FROM  `news_entry` ORDER BY id DESC LIMIT 500

Auftrag id.

Da id ist höchstwahrscheinlich ein PRIMARY KEY für Ihren Tisch, und jede PRIMARY KEY hat einen impliziten Index es Sicherung, nicht ORDER BY nicht zu sortieren muß.

dpub ist ein berechnetes Feld und MySQL unterstützt keine Indizes für berechnete Felder. Allerdings ORDER BY dt_published ist ein ORDER BY dpub auch.

Sie benötigen eine Abfrage auf diese ändern:

SELECT *, date(dt_published) as dpub FROM `news_entry` order by date_published DESC LIMIT 500

und erstellen einen Index für news_entry (dt_published).

Update:

Da DATE eine monotone Funktion ist, können Sie diesen Trick anwenden:

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

Diese Abfrage führt Folgendes aus:

  • Wählt der 500th Datensatz in dt_published DESC Reihenfolge oder der erste Datensatz geschrieben sollte es weniger als 500 Datensätze in der Tabelle.

  • Holt alle Datensätze geschrieben später als das Datum des letzten Datensatz ausgewählt. Da DATE(x) immer weniger oder gleich x, kann es mehr als 500 Aufzeichnungen, aber immer noch viel weniger als die gesamte Tabelle.

  • Aufträge und Grenzen dieser Aufzeichnungen als angemessen.

Sie können diesen Artikel interessant finden, da es ein ähnliches Problem behandelt:

Andere Tipps

benötigen einen Index für dt_published. Können Sie sich die Abfragepläne für die beiden Abfragen schreiben?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top