Sql 在制定计划时,博士后已经“看到”了你在说什么。@DEM根据我的经验,我还没有发现它能解决这个问题。通过这样做,我在查询速度方面有了惊人的提高。让我们看看他是否用这种方法改变了速度。这种方法的执行时间没有改变。我不同意。尽管最具选择性的谓词在site\u i

Sql 在制定计划时,博士后已经“看到”了你在说什么。@DEM根据我的经验,我还没有发现它能解决这个问题。通过这样做,我在查询速度方面有了惊人的提高。让我们看看他是否用这种方法改变了速度。这种方法的执行时间没有改变。我不同意。尽管最具选择性的谓词在site\u i,sql,performance,postgresql,optimization,join,Sql,Performance,Postgresql,Optimization,Join,在制定计划时,博士后已经“看到”了你在说什么。@DEM根据我的经验,我还没有发现它能解决这个问题。通过这样做,我在查询速度方面有了惊人的提高。让我们看看他是否用这种方法改变了速度。这种方法的执行时间没有改变。我不同意。尽管最具选择性的谓词在site\u id上可能是正确的,但对includepublished\u at中索引的更改确实会产生潜在的巨大差异。这是因为按照站点id进行筛选之后,连接可以通过索引查找而不是顺序扫描来完成。但是,如果他的博客每个都包含10万篇文章,那么索引(blog\u


在制定计划时,博士后已经“看到”了你在说什么。@DEM根据我的经验,我还没有发现它能解决这个问题。通过这样做,我在查询速度方面有了惊人的提高。让我们看看他是否用这种方法改变了速度。这种方法的执行时间没有改变。我不同意。尽管最具选择性的谓词在
site\u id
上可能是正确的,但对include
published\u at
中索引的更改确实会产生潜在的巨大差异。这是因为按照站点id进行筛选之后,连接可以通过索引查找而不是顺序扫描来完成。但是,如果他的博客每个都包含10万篇文章,那么索引
(blog\u id,published\u at)
将导致以错误的顺序检索
100k*个blog
行,然后需要对其进行前n排序。相比之下,按照我的建议添加额外的site_id字段将允许计划者直接获取前5行。实际上,限制为5确保每个blog_id只需要5篇文章。你的建议确实保证了查询的快速解决方案,但我会担心这种非规范化,除非能证明它是绝对必要的。遵循这种模式对所有查询进行去规范化和索引可能会导致非常臃肿的模式。因此,我并不反对你的主张,只是我将其视为“如果需要,必须”选项,而不是偏好。“实际上,限制5确保每个博客id只需要5篇文章。”事实上。。。看看解释/分析。排名前五的是从243个博客中筛选出的50861篇文章。PG在top-n排序之前获取每个最后适用的帖子。一致认为,非规范化通常是不好的。但这是其中一个实际可行的例子。(另一方面,他的另一个选择是使用触发器维护“最新发布”表。)这只是因为目前数据完全无序(关于
发布的数据)。使用建议的索引,您将有效地拥有多个有序列表(每个blog_id对应一个)。然后可以选择这些有序列表中的前5个进行合并排序,从而得到所需的最后5个。任何有序列表中的第6个条目保证永远不需要。事实上,这是
5*blog\u count
而不仅仅是
5
,而不是您可能担心的
n*blog\u count
。这似乎没有解决OPs原则问题:如何提高查询成本,从而获得更快的执行。这并没有改变执行时间解释计划是否显示使用了新索引?或者您是否尝试过应用两个索引而不是一个?如果其他方法都不起作用,那么您的应用程序似乎一直在修改模式。查看我的编辑。。。
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
)
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
)
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
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
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
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)
CREATE TABLE "blog_cached_posts" (
    "id" int4 NOT NULL DEFAULT nextval('blog_cached_posts_id_seq'::regclass),
    ...
    "published_at" timestamp(6) NULL,
    "site_id" int4,
    "blog_id" int4,
    ...
)
SELECT "blog_cached_posts".*
FROM "blog_cached_posts"
WHERE site_id = 80
ORDER BY published_at desc nulls last
LIMIT 5
SELECT blog_cached_posts.*
FROM blogs
join blog_cached_posts on blogs.id = blog_cached_posts.blog_id AND published_at IS NOT NULL
WHERE blogs.site_id = 80
ORDER BY published_at desc
LIMIT 5