Pregunta

Yo uso el siguiente código para seleccionar entradas de noticias populares (por fecha) de la base de datos:

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

Para comparar las velocidades de ejecución de una consulta normal y éste me encontré con las siguientes consultas de 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]

Como se puede ver la consulta normal es mucho más rápido. ¿Hay una manera de acelerar este proceso?

¿Es posible utilizar las vistas de MySQL con Django?

Me doy cuenta de que sólo podía dividir el campo de fecha y hora en dos campos (fecha y hora), pero tengo curiosidad.


Estructura:

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;
¿Fue útil?

Solución

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

Esta consulta órdenes en dpub, mientras éste:

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

órdenes de id.

Desde id es más probablemente un PRIMARY KEY para su mesa, y cada PRIMARY KEY tiene un índice implícito respaldo que, ORDER BY no tiene por qué tipo.

dpub es un campo calculado y MySQL no soporta índices en campos calculados. Sin embargo, ORDER BY dt_published es un ORDER BY dpub también.

Es necesario cambiar la consulta a esto:

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

y crear un índice en news_entry (dt_published).

Actualización:

Desde DATE es una función monótona, es posible emplear este truco:

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

Esta consulta hace lo siguiente:

  • selecciona el registro 500th con el fin dt_published DESC, o el primer registro publicado no debe ser inferior a los registros 500 en la tabla.

  • Obtiene todos los registros enviado a más tardar el fecha del último registro seleccionado. Desde DATE(x) es siempre menor o igual a x, no puede haber más de registros 500, pero aún mucho menos que toda la tabla.

  • Órdenes y límites de estos registros según sea apropiado.

Usted puede encontrar este artículo interesante, ya que cubre un problema similar:

Otros consejos

posible que tenga un índice en dt_published. Podría publicar los planes de consulta para las dos consultas?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top