ускорение MySQL запросов / MySQL просмотров в Django - PullRequest
1 голос
/ 07 сентября 2010

Я использую следующий код для выбора популярных новостей (по дате) из базы данных:

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

Чтобы сравнить скорости выполнения обычного запроса и этого, я запустил следующие запросы 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]

Как видите, обычный запрос выполняется намного быстрее. Есть ли способ ускорить это?

Возможно ли использовать представления MySQL с Django?

Я понимаю, что мог бы просто разделить поле даты и времени на два поля (дата и время), но мне любопытно.


Состав:

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;

Ответы [ 2 ]

2 голосов
/ 07 сентября 2010
SELECT *, date(dt_published) as dpub FROM `news_entry` order by dpub DESC LIMIT 500

Этот запрос заказывает на dpub, а этот:

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

заказов на id.

Поскольку id, скорее всего, PRIMARY KEY для вашей таблицы, и каждый PRIMARY KEY имеет неявный индекс, поддерживающий его, ORDER BY сортировать не нужно.

dpub является вычисляемым полем, а MySQL не поддерживает индексы для вычисляемых полей. Однако ORDER BY dt_published также является ORDER BY dpub.

Вам нужно изменить свой запрос следующим образом:

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

и создайте индекс для news_entry (dt_published).

Обновление:

Поскольку DATE является монотонной функцией, вы можете использовать этот трюк:

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

Этот запрос выполняет следующие действия:

  • Выбирает запись 500th в порядке dt_published DESC, или первая опубликованная запись должна содержать менее 500 записей в таблице.

  • Извлекает все записи, опубликованные позднее даты последней выбранной записи. Поскольку DATE(x) всегда меньше или равно x, может быть больше 500 записей, но все же намного меньше, чем вся таблица.

  • Заказывает и ограничивает эти записи соответствующим образом.

Эта статья может показаться вам интересной, поскольку она охватывает аналогичную проблему:

0 голосов
/ 07 сентября 2010

Может потребоваться индекс на dt_published. Не могли бы вы опубликовать планы запросов для двух запросов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...