[英]Postgres order by foreign key performance?
我在通过外键在Postgres中订购有一个奇怪的(?)问题。 这是第二个表和查询,使用order by花费的时间要长于没有。
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
什么会引起问题? 是查询吗? 配置? 我应该检查任何特定的配置吗? 在我的最后一个问题中,有更复杂的查询,但该查询根本不复杂。 有什么建议么?
顺便说一句。 该查询由Django生成(准确地说是django-taggit)。 顺便说一句。 第二部分,它一点都不差劲的硬件(i7、16 GB的RAM,用于操作系统和数据的RAID 10 3x2 +用于WAL的2个RAID1磁盘,512 MB的RAID缓存+ BBU)
纯文本查询:
选择“ spoleczniak_zdjecia”。“ id”,“ spoleczniak_zdjecia”。“ postac_id”,“ spoleczniak_zdjecia”。“ zdjecie”,“ spoleczniak_zdjecia”。“ opis”,“ spoleczniacz_zdjenia”。“数据”,“ ssandraczniak_zdjecia”。“ 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”。“ kariera”来自“ spoleczniak_zdjecia” INNER JOIN“ taggit_taggeditem” ON(“ spoleczniak_zdjecia”。“ id” =“ taggit_taggeditem”。“ object_id”)INNER JOIN“ taggit_tag” ON(=“ taggit_taggeditem” “ taggit_tag”。“ id”)INNER JOIN“ postac_postacie” ON(“ spoleczniak_zdjecia ..” postac_id“ =” postac_postacie“。” id“)在哪里(” taggit_tag“。” slug“ ='ja'AND” taggit_taggeditem“。” content_type_id“ = 922)ORDER BY” spoleczniak_zdjecia“。” id “ DESC LIMIT 28;
区别就在EXPLAIN输出的第二行:
-> Sort (cost=27.88..27.89 rows=7 width=198) (actual time=2984.688..2984.692 rows=28 loops=1)
注意,“实际时间”几乎是整个查询时间。 排序不仅需要进行一堆比较(即对任何内容进行排序的成本),而且还需要额外的数据管理,服务器需要将一些数据(行或行的指针)复制到一个临时位置,以便可以在不干扰其他任何内容的情况下进行排序。
除非您感到幸运并且排序与磁盘上的顺序匹配,否则任何查询将花费更长的时间进行排序,并且优化器可以注意到它们匹配。
第二个返回您找到的前28条记录,无论顺序如何。
首先,您必须订购结果,然后返回28条第一条记录。
如果未修改数据,则使用ORDER BY
的查询每次都会返回相同的28条记录。
但是第二个查询每次执行时都可以返回28个不同的记录。 结果无法保证。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.