Slow Postgres JOIN Запрос - PullRequest
       5

Slow Postgres JOIN Запрос

3 голосов
/ 17 сентября 2010

Я пытаюсь оптимизировать медленный запрос, сгенерированный Django ORM.Это запрос многие ко многим.Для запуска требуется более 1 минуты.

Таблицы содержат много данных, но они невелики (400 000 строк в sp_article и 300 000 строк в sp_article_categories)

#categories.article_set.filter(post_count__lte=50)

EXPLAIN ANALYZE SELECT * 
                  FROM "sp_article" 
            INNER JOIN "sp_article_categories" ON ("sp_article"."id" = "sp_article_categories"."article_id") 
                WHERE ("sp_article_categories"."category_id" = 1081  
                  AND "sp_article"."post_count" <= 50 )

Nested Loop  (cost=0.00..6029.01 rows=656 width=741) (actual time=0.472..25.724 rows=1266 loops=1)
  ->  Index Scan using sp_article_categories_category_id on sp_article_categories  (cost=0.00..848.82 rows=656 width=12) (actual time=0.015..1.305 rows=1408 loops=1)
        Index Cond: (category_id = 1081)
  ->  Index Scan using sp_article_pkey on sp_article  (cost=0.00..7.88 rows=1 width=729) (actual time=0.014..0.015 rows=1 loops=1408)
        Index Cond: (sp_article.id = sp_article_categories.article_id)
        Filter: (sp_article.post_count <= 50)
Total runtime: 26.536 ms

Iесть индекс:

sp_article_categories.article_id (type: btree)
sp_article_categories.category_id
sp_article.post_count (type: btree)

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

Спасибо!

Ответы [ 5 ]

1 голос
/ 18 сентября 2010

Вы предоставили здесь важную информацию - объясните, проанализируйте. Это не показывает время выполнения 1 секунды, оно показывает 20 миллисекунд. Так что - либо это не выполняемый запрос, либо проблема в другом месте.

Единственная разница между объяснением и анализом в реальном приложении заключается в том, что результаты фактически не возвращаются. Вам понадобится много данных, чтобы замедлить процесс до 1 секунды.

Все остальные предложения не принимаются во внимание, поскольку они игнорируют тот факт, что запрос не медленный. У вас есть соответствующие индексы (обе стороны объединения используют сканирование индекса), и планировщик в первую очередь способен фильтровать таблицу категорий (в этом и заключается весь смысл иметь наполовину достойный планировщик запросов).

Итак - сначала нужно выяснить, что именно медленно ...

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

Я предполагаю, что вы запустили анализ базы данных, чтобы получить свежую статистику.

Похоже, что соединение между sp_article.id и sp_article_categories.article_id является дорогостоящим. Какой тип данных является идентификатор статьи, числовой? Если это не так, возможно, вам следует подумать о том, чтобы сделать его числовым - целочисленным или bigint, независимо от того, что соответствует вашим потребностям. Это может иметь большое значение в производительности в соответствии с моим опытом. Надеюсь, это поможет.

Ура! // Джон

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

С точки зрения чистого SQL ваше объединение будет более эффективным, если в вашей базовой таблице меньше строк, и условия WHERE выполняются для этой таблицы перед ее соединением с другой.

Посмотрите, сможете ли вы сначала заставить Django выбирать из категорий, а затем отфильтровать category_id перед присоединением к таблице артикулов.

Псевдокод следует:

SELECT * FROM categories c
INNER JOIN articles a
    ON c.category_id = 1081
    AND c.category_id = a.category_id

И поставить индекс на category_id, как предполагает Стивен.

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

Вы можете использовать имена полей вместо * тоже.

выберите [поля] из ....

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

Поместить индекс на sp_article_categories.category_id

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