Заказ Postgres по производительности внешнего ключа? - PullRequest
1 голос
/ 31 августа 2011

У меня странная (?) Проблема с заказом в Postgres по внешнему ключу.Это вторая таблица и запрос, который занимает гораздо больше времени при заказе, чем без него.

EXPLAIN ANALYZE SELECT "spoleczniak_zdjecia"."id", "spoleczniak_zdjecia"."postac_id", "spoleczniak_zdjecia"."zdjecie", "spoleczniak_zdjecia"."opis", "spoleczniak_zdjecia"."data", "spoleczniak_zdjecia"."avatar", "spoleczniak_zdjecia"."tagi", "postac_postacie"."id", "postac_postacie"."user_id", "postac_postacie"."avatar", "postac_postacie"."ikonka", "postac_postacie"."imie", "postac_postacie"."nazwisko", "postac_postacie"."pseudonim", "postac_postacie"."plec", "postac_postacie"."wzrost", "postac_postacie"."waga", "postac_postacie"."ur_tydz", "postac_postacie"."ur_rok", "postac_postacie"."ur_miasto_id", "postac_postacie"."akt_miasto_id", "postac_postacie"."kasa", "postac_postacie"."punkty", "postac_postacie"."zmeczenie", "postac_postacie"."zdrowie", "postac_postacie"."kariera" FROM "spoleczniak_zdjecia" INNER JOIN "taggit_taggeditem" ON ("spoleczniak_zdjecia"."id" = "taggit_taggeditem"."object_id") INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") INNER JOIN "postac_postacie" ON ("spoleczniak_zdjecia"."postac_id" = "postac_postacie"."id") WHERE ("taggit_tag"."slug" = 'ja' AND "taggit_taggeditem"."content_type_id" = 922 ) ORDER BY "spoleczniak_zdjecia"."id" DESC LIMIT 28;
                                                                                QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=27.88..27.89 rows=7 width=198) (actual time=2984.689..2984.697 rows=28 loops=1)
   ->  Sort  (cost=27.88..27.89 rows=7 width=198) (actual time=2984.688..2984.692 rows=28 loops=1)
         Sort Key: spoleczniak_zdjecia.id
         Sort Method: top-N heapsort  Memory: 32kB
         ->  Nested Loop  (cost=2.31..27.78 rows=7 width=198) (actual time=1.063..2974.901 rows=9091 loops=1)
               ->  Nested Loop  (cost=2.31..22.02 rows=7 width=109) (actual time=1.057..2899.010 rows=9091 loops=1)
                     ->  Nested Loop  (cost=2.31..19.92 rows=7 width=4) (actual time=1.046..2848.853 rows=9103 loops=1)
                           ->  Index Scan using taggit_tag_slug on taggit_tag  (cost=0.00..4.27 rows=1 width=4) (actual time=0.025..0.027 rows=1 loops=1)
                                 Index Cond: ((slug)::text = 'ja'::text)
                           ->  Bitmap Heap Scan on taggit_taggeditem  (cost=2.31..15.56 rows=7 width=8) (actual time=1.019..2847.244 rows=9103 loops=1)
                                 Recheck Cond: (tag_id = taggit_tag.id)
                                 Filter: (content_type_id = 922)
                                 ->  Bitmap Index Scan on taggit_taggeditem_tag_id  (cost=0.00..2.31 rows=7 width=0) (actual time=0.954..0.954 rows=9103 loops=1)
                                       Index Cond: (tag_id = taggit_tag.id)
                     ->  Index Scan using spoleczniak_zdjecia_pkey on spoleczniak_zdjecia  (cost=0.00..0.29 rows=1 width=109) (actual time=0.005..0.005 rows=1 loops=9103)
                           Index Cond: (id = taggit_taggeditem.object_id)
               ->  Index Scan using postac_postacie_pkey on postac_postacie  (cost=0.00..0.81 rows=1 width=89) (actual time=0.007..0.007 rows=1 loops=9091)
                     Index Cond: (id = spoleczniak_zdjecia.postac_id)
 Total runtime: 2984.760 ms

А вот без заказа по:

EXPLAIN ANALYZE SELECT "spoleczniak_zdjecia"."id", "spoleczniak_zdjecia"."postac_id", "spoleczniak_zdjecia"."zdjecie", "spoleczniak_zdjecia"."opis", "spoleczniak_zdjecia"."data", "spoleczniak_zdjecia"."avatar", "spoleczniak_zdjecia"."tagi", "postac_postacie"."id", "postac_postacie"."user_id", "postac_postacie"."avatar", "postac_postacie"."ikonka", "postac_postacie"."imie", "postac_postacie"."nazwisko", "postac_postacie"."pseudonim", "postac_postacie"."plec", "postac_postacie"."wzrost", "postac_postacie"."waga", "postac_postacie"."ur_tydz", "postac_postacie"."ur_rok", "postac_postacie"."ur_miasto_id", "postac_postacie"."akt_miasto_id", "postac_postacie"."kasa", "postac_postacie"."punkty", "postac_postacie"."zmeczenie", "postac_postacie"."zdrowie", "postac_postacie"."kariera" FROM "spoleczniak_zdjecia" INNER JOIN "taggit_taggeditem" ON ("spoleczniak_zdjecia"."id" = "taggit_taggeditem"."object_id") INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") INNER JOIN "postac_postacie" ON ("spoleczniak_zdjecia"."postac_id" = "postac_postacie"."id") WHERE ("taggit_tag"."slug" = 'ja' AND "taggit_taggeditem"."content_type_id" = 922 ) LIMIT 28;
                                                                            QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=2.31..27.78 rows=7 width=198) (actual time=1.113..1.482 rows=28 loops=1)
   ->  Nested Loop  (cost=2.31..27.78 rows=7 width=198) (actual time=1.112..1.477 rows=28 loops=1)
         ->  Nested Loop  (cost=2.31..22.02 rows=7 width=109) (actual time=1.102..1.292 rows=28 loops=1)
               ->  Nested Loop  (cost=2.31..19.92 rows=7 width=4) (actual time=1.092..1.145 rows=28 loops=1)
                     ->  Index Scan using taggit_tag_slug on taggit_tag  (cost=0.00..4.27 rows=1 width=4) (actual time=0.017..0.017 rows=1 loops=1)
                           Index Cond: ((slug)::text = 'ja'::text)
                     ->  Bitmap Heap Scan on taggit_taggeditem  (cost=2.31..15.56 rows=7 width=8) (actual time=1.072..1.118 rows=28 loops=1)
                           Recheck Cond: (tag_id = taggit_tag.id)
                           Filter: (content_type_id = 922)
                           ->  Bitmap Index Scan on taggit_taggeditem_tag_id  (cost=0.00..2.31 rows=7 width=0) (actual time=0.989..0.989 rows=9103 loops=1)
                                 Index Cond: (tag_id = taggit_tag.id)
               ->  Index Scan using spoleczniak_zdjecia_pkey on spoleczniak_zdjecia  (cost=0.00..0.29 rows=1 width=109) (actual time=0.004..0.005 rows=1 loops=28)
                     Index Cond: (id = taggit_taggeditem.object_id)
         ->  Index Scan using postac_postacie_pkey on postac_postacie  (cost=0.00..0.81 rows=1 width=89) (actual time=0.005..0.005 rows=1 loops=28)
               Index Cond: (id = spoleczniak_zdjecia.postac_id)
 Total runtime: 1.562 ms

Что может вызвать проблемы?Это запрос?Config?Какой-то конкретный конфиг я должен проверить?В моем последнем вопросе был более сложный запрос, но этот запрос совсем не сложен.Любые предложения?

И кстати.этот запрос генерируется Django (если быть точным, django-taggit).И кстати.часть II, это совсем не плохое аппаратное обеспечение (i7, 16 ГБ ОЗУ, RAID 10 3x2 для ОС и данных + 2 диска RAID1 для WAL, 512 МБ RAID-кеша + BBU)

Простой текстовый запрос:

ВЫБРАТЬ «spoleczniak_zdjecia». «Id», «spoleczniak_zdjecia». «Postac_id», «spoleczniak_zdjecia». «Zdjecie», «spoleczniak_zdjecia»."avatar", "spoleczniak_zdjecia". "tagi", "postac_postacie". "id", "postac_postacie". "user_id", "postac_postacie". "avatar", "postac_postacie". "ikonka", "postac_posc.""," postac_postacie "." nazwisko "," postac_postacie "." pseudonim "," postac_postacie "." plec "," postac_postacie "." wzrost "," postac_postacie "." waga "," posta "postac. postac."postac_postacie". "ur_rok", "postac_postacie". "ur_miasto_id", "postac_postacie". "akt_miasto_id", "postac_postacie". "kasa", "postac_postacie"."." zdrowie "," postac_postacie "." kariera "ИЗ" spoleczniak_zdjecia "ВНУТРЕННЕЕ СОЕДИНЕНИЕ" taggit_taggeditem "ON (" spoleczniak_zdjecia "." id "=" taggit_taggeditem "." object_id ") INNER JOIN" taggit_tag "ON (" taggit_taggeditem "." tag_id "=" taggit_tag "." id ") INNER JOIN" postac_pos ""spoleczniak_zdjecia". "postac_id" = "postac_postacie". "id") WHERE ("taggit_tag". "slug" = 'ja' И "taggit_taggeditem". "content_type_id" = 922) ORDER BY "spoleczniak_zdjeLIMIT 28;

Ответы [ 2 ]

1 голос
/ 31 августа 2011

Разница прямо здесь во второй строке вывода EXPLAIN:

->  Sort  (cost=27.88..27.89 rows=7 width=198) (actual time=2984.688..2984.692 rows=28 loops=1)

Обратите внимание, что "фактическое время" - это почти все время запроса.Сортировка требует не только ряда сравнений (т.е. затрат на сортировку чего-либо), но и дополнительного управления данными, серверу необходимо скопировать некоторые данные (строки или указатели на строки) во временное расположение, чтобы их можно было сортировать, не мешая чему-либо другому..

Любой запрос займет больше времени при сортировке, если вам не повезет, и ваша сортировка не соответствует порядку на диске, и оптимизатор может заметить, что они совпадают.

0 голосов
/ 31 августа 2011

Вторая возвращает вам первые 28 найденных записей независимо от порядка.

Сначала вы должны заказать результаты, ТО вернув вам 28 первых записей.

Если данные не изменены, запрос с ORDER BY будет каждый раз возвращать одни и те же 28 записей.

Но второй запрос может возвращает 28 разных записей при каждом его выполнении. Результат не гарантирован.

...