Postgres - Langsame einfach join mit where-Klausel

Ich bin mit einigen Schwierigkeiten eine Abfrage optimieren, und hatte gehofft, dass hier jemand möglicherweise ein paar Hinweise.

Ich habe zwei Tabellen:

CREATE TABLE "blog_cached_posts" (
    "id" int4 NOT NULL DEFAULT nextval('blog_cached_posts_id_seq'::regclass),
    "title" varchar(255),
    "content" text,
    "content_encoded" text,
    "published_at" timestamp(6) NULL,
    "written_by" varchar(255),
    "link" varchar(255),
    "blog_id" int4,
    "guid" varchar(255),
    "created_at" timestamp(6) NULL,
    "updated_at" timestamp(6) NULL,
    "is_highlighted_post" bool DEFAULT false
)

Mit einem index auf blog_cached_posts.blog_id

CREATE TABLE "blogs" (
    "id" int4 NOT NULL DEFAULT nextval('blogs_id_seq'::regclass),
    "site_id" int4,
    "image_id" int4,
    "name" varchar(255),
    "description" text,
    "url" varchar(255),
    "rss_feed_url" varchar(255),
    "active" bool DEFAULT true,
    "created_at" timestamp(6) NULL,
    "updated_at" timestamp(6) NULL,
    "date_highlighted" date,
    "highlighted_category_feed_url" varchar(255),
    "position" int4
)

Mit einem index auf blogs.site_id

Dies ist die Abfrage:

SELECT "blog_cached_posts".*
FROM "blog_cached_posts"
join blogs on blogs.id = blog_cached_posts.blog_id
WHERE ((published_at IS NOT NULL) AND (blogs.site_id = 80))
ORDER BY published_at desc
LIMIT 5

Hier ist ein EXPLAIN ANALYZE:

Limit  (cost=9499.16..9499.17 rows=5 width=1853) (actual time=118.538..118.539 rows=5 loops=1)
  ->  Sort  (cost=9499.16..9626.31 rows=50861 width=1853) (actual time=118.536..118.537 rows=5 loops=1)
        Sort Key: blog_cached_posts.published_at
        Sort Method:  top-N heapsort  Memory: 33kB
        ->  Hash Join  (cost=16.25..8654.38 rows=50861 width=1853) (actual time=0.186..82.910 rows=48462 loops=1)
              Hash Cond: (blog_cached_posts.blog_id = blogs.id)
              ->  Seq Scan on blog_cached_posts  (cost=0.00..7930.94 rows=52954 width=1853) (actual time=0.042..56.635 rows=52950 loops=1)
                    Filter: (published_at IS NOT NULL)
              ->  Hash  (cost=13.21..13.21 rows=243 width=4) (actual time=0.135..0.135 rows=243 loops=1)
                    ->  Seq Scan on blogs  (cost=0.00..13.21 rows=243 width=4) (actual time=0.007..0.089 rows=243 loops=1)
                          Filter: (site_id = 80)
Total runtime: 118.591 ms

Gibt es eine Möglichkeit, um dies zu optimieren, jenseits der ~120ms ist es derzeit?

BEARBEITEN

Hier ist, was ich am Ende tun. (Nach dem Lesen der Kommentar von @ypercube)

Ich fügte hinzu, einen index zu blog_cached_posts:

CREATE INDEX \"blog_cached_posts_published_at\" ON \"public\".\"blog_cached_posts\" USING btree(published_at DESC NULLS LAST);
COMMENT ON INDEX \"public\".\"blog_cached_posts_published_at\" IS NULL;

Und ich änderte die wählen auf den folgenden:

SELECT "blog_cached_posts".*
FROM "blog_cached_posts"
join blogs on blogs.id = blog_cached_posts.blog_id
WHERE published_at is not null and blogs.site_id = 80
ORDER BY published_at desc nulls last
LIMIT 5

Dieser brachte die Ausführungszeit auf ~3ms.

Hier ist der neue Ausführungsplan:

Limit  (cost=0.00..3.85 rows=5 width=1849) (actual time=0.027..0.047 rows=5 loops=1)
  ->  Nested Loop  (cost=0.00..39190.01 rows=50872 width=1849) (actual time=0.026..0.046 rows=5 loops=1)
        ->  Index Scan using blog_cached_posts_published_at on blog_cached_posts  (cost=0.00..24175.16 rows=52965 width=1849) (actual time=0.017..0.023 rows=5 loops=1)
              Filter: (published_at IS NOT NULL)
        ->  Index Scan using blogs_pkey on blogs  (cost=0.00..0.27 rows=1 width=4) (actual time=0.003..0.004 rows=1 loops=5)
              Index Cond: (blogs.id = blog_cached_posts.blog_id)
              Filter: (blogs.site_id = 80)
Total runtime: 0.086 ms
  • Haben Sie versucht, ändern Sie Ihre index auf blog_cached_posts aus der Spalte blog_id den Spalten blog_id, published_at?
  • Ich würde auch versuchen eine einfache index auf published_at
  • hat u versuchen meine Lösung? Wenn ja, postet bitte die Ergebnisse. thx.
  • Sorry, hatte noch keine Zeit, um zu überdenken Sie das problem noch. Testen Sie Ihre Vorschläge heute 🙂
  • Dein Vorschlag hat funktioniert. Das hinzufügen eines einfachen index für published_at desc nulls last, brachte der Ausführung-Zeit bis zu ~3ms. - Sollten Sie eine Antwort mit der Lösung 🙂
  • sind Sie sicher, dass dies die Lösung war und auch nicht, dass die Abfrage zwischengespeichert wurden? Haben Sie versucht, mit LIMIT 50 oder LIMIT 200 ? Ist es auch schneller?
  • Oh, ich sehe die anderen Ausführungsplan, OK.

Schreibe einen Kommentar