У меня возникли проблемы с оптимизацией запроса, и я надеялся, что кто-то здесь сможет предоставить несколько указателей.
У меня есть две таблицы:
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
)
С индексомна 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
)
С индексом для blogs.site_id
Это запрос:
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
Вот ОБЪЯСНИТЕЛЬНЫЙ АНАЛИЗ:
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
Есть ли способ оптимизировать это, помимо ~ 120 мс, которые он в настоящее время принимает?
РЕДАКТИРОВАТЬ
Вот что я в итоге сделал.(После прочтения комментария @ypercube)
Я добавил индекс для 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;
И изменил выбор на следующее:
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
Этодовел время выполнения до ~ 3 мс.
Вот новый план выполнения:
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