velocizzando le query MySQL / MySQL viste in Django
-
01-10-2019 - |
Domanda
Io uso il seguente codice per selezionare le voci di notizie popolari (per data) dal database:
popular = Entry.objects.filter(type='A', is_public=True).extra(select = {'dpub': 'date(dt_published)'}).order_by('-dpub', '-views', '-dt_written', 'headline')[0:5]
Per confrontare le velocità di esecuzione di una query normale e questo mi sono imbattuto le seguenti query 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]
Come si può vedere la query normale è molto più veloce. C'è un modo per accelerare questo?
E 'possibile utilizzare le visualizzazioni MySQL con Django?
Mi rendo conto che ho potuto solo dividere il campo datetime in due campi (data e ora), ma sono curioso.
Struttura:
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;
Soluzione
SELECT *, date(dt_published) as dpub FROM `news_entry` order by dpub DESC LIMIT 500
Nella query Ordini dpub
, mentre questo:
SELECT * , DATE( dt_published ) AS dpub FROM `news_entry` ORDER BY id DESC LIMIT 500
ordini su id
.
Dal id
è più probabilmente un PRIMARY KEY
per la vostra tavola, e ciascuno PRIMARY KEY
ha un indice implicito sostenerla, ORDER BY
non ha bisogno di sorta.
dpub
è un campo calcolato e MySQL
non supporta gli indici sui campi calcolati. Tuttavia, è un ORDER BY dt_published
ORDER BY dpub
pure.
È necessario modificare la tua ricerca a questo:
SELECT *, date(dt_published) as dpub FROM `news_entry` order by date_published DESC LIMIT 500
e creare un indice su news_entry (dt_published)
.
Aggiornamento:
Dato DATE
è una funzione monotona, si può impiegare questo trucco:
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
Questa query fa il seguente:
-
seleziona il record
500th
al finedt_published DESC
, o il primo record inviato ci dovrebbe essere inferiore a record500
nella tabella. -
Recupera tutti i record inviati entro e non oltre il data ??strong> l'ultimo record selezionato. Dal momento che
DATE(x)
è sempre minore o uguale ax
, non ci può essere più di record500
, ma ancora molto meno di quanto l'intera tabella. -
Ordini e limiti di questi record a seconda dei casi.
Si possono trovare interessante questo articolo, in quanto copre un problema simile:
Altri suggerimenti
Può essere necessario un indice su dt_published
. Potresti postare i piani di query per le due query?