Question

J'utilise le code suivant pour sélectionner les entrées de nouvelles populaires (par date) de la base de données:

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

Pour comparer les vitesses d'exécution d'une requête normale et celui-ci j'ai couru les requêtes MySQL suivantes:

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]

Comme vous pouvez le voir la requête normale est beaucoup plus rapide. Est-il un moyen d'accélérer ce?

Est-il possible d'utiliser des vues MySQL avec django?

Je me rends compte que je pouvais diviser le champ datetime en deux champs (date et heure), mais je suis curieux.


Structure:

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;
Était-ce utile?

La solution

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

ORDONNE de requête sur dpub, alors que celui-ci:

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

commandes sur id.

Depuis id est très probablement un PRIMARY KEY pour votre table, et chaque PRIMARY KEY a un indice implicite le soutenir, ORDER BY n'a pas besoin de trier.

dpub est un champ et MySQL calculé ne prend pas en charge les index sur les champs calculés. Cependant, ORDER BY dt_published est un ORDER BY dpub aussi bien.

Vous devez changer votre requête à ceci:

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

et créer un index sur news_entry (dt_published).

Mise à jour:

Depuis DATE est une fonction monotone, vous pouvez employer cette astuce:

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

Cette requête effectue les opérations suivantes:

  • Sélectionne le dossier de 500th afin de dt_published DESC, ou le premier enregistrement posté devrait y avoir moins de dossiers de 500 dans le tableau.

  • Récupère tous les enregistrements affichés plus tard le date du dernier enregistrement sélectionné. Depuis DATE(x) est toujours inférieure ou égale à x, il peut y avoir plus de dossiers de 500, mais toujours beaucoup moins que la table.

  • Les commandes et les limites de ces dossiers, selon le cas.

Vous pouvez trouver cet article intéressant, car il couvre un problème similaire:

Autres conseils

mai besoin d'un index sur dt_published. Pourriez-vous afficher les plans de requête pour les deux requêtes?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top