Beschleunigung der MySQL-Abfragen / mysql Ansichten in django
-
01-10-2019 - |
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;
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 indt_published DESC
Reihenfolge oder der erste Datensatz geschrieben sollte es weniger als500
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 gleichx
, kann es mehr als500
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?