PostgreSQL查询优化,阅读解释

PostgreSQL查询优化,阅读解释,postgresql,sql-execution-plan,Postgresql,Sql Execution Plan,我正在读取对查询运行解释的输出。结果是: 我看到在第34行,DB正在做一个非常昂贵的索引扫描,结果删除了一行 我读对了吗?还有,是什么原因造成的 查询: explain analyze select *, posts.type as type, posts.created as created, posts.image_url as image_url, posts.id as post_id, posts.organization_id as id, urls.image_url as

我正在读取对查询运行解释的输出。结果是:

我看到在第34行,DB正在做一个非常昂贵的索引扫描,结果删除了一行

我读对了吗?还有,是什么原因造成的

查询:

explain analyze select *, posts.type as type, posts.created as created, posts.image_url as image_url, posts.id as post_id, posts.organization_id as id,
    urls.image_url as url_image_url,
    ts_headline('english',posts.text , to_tsquery('english', 'state')  , $$StartSel='<span class="text-highlight">',StopSel=</span>, HighlightAll=true$$) as text,
    ts_headline('english',posts.attachment_description, to_tsquery('english', 'state')  , $$StartSel='<span class="text-highlight">',StopSel=</span>, HighlightAll=true$$) as attachment_description,
    ts_headline('english',posts.attachment_title, to_tsquery('english', 'state')  , $$StartSel='<span class="text-highlight">',StopSel=</span>, HighlightAll=true$$) as attachment_title
     from vision2.posts15 as posts join vision2.organizations on organizations.id=posts.organization_id left join vision2.urls on urls.id = posts.url_id where  chunks @@ to_tsquery('english', 'state')   and string_to_array(upper(organizations.irs_state), '') && array['NJ']  and Date(posts.created) >= '2017-08-10' and Date(posts.created) <= '2017-08-24' and Date(posts.partition_date) >= '2017-08-10' and Date(posts.partition_date) <= '2017-08-24'  order by posts.created desc   offset 0 limit 40

尝试在执行联接之前限制数据。您可以使用CTE,因为它们只被物化一次,并且可以像优化围栏或临时表一样工作

因此,您的查询可能如下所示:

WITH cte_posts AS (
  select type, created, image_url, id as post_id, organization_id as id, url_id,
         ts_headline('english',
                     text,
                     to_tsquery('english', 'state'),
                     $$StartSel='<span class="text-highlight">',StopSel=</span>, HighlightAll=true$$) as text,
         ts_headline('english',
                     attachment_description,
                     to_tsquery('english', 'state'),
                     $$StartSel='<span class="text-highlight">',StopSel=</span>, HighlightAll=true$$) as attachment_description,
         ts_headline('english',
                     attachment_title,
                     to_tsquery('english', 'state'),
                     $$StartSel='<span class="text-highlight">',StopSel=</span>, HighlightAll=true$$) as attachment_title
  from vision2.posts15
  where Date(created) BETWEEN '2017-08-10' AND '2017-08-24'
  and Date(partition_date) BETWEEN '2017-08-10' AND '2017-08-24'
  AND chunks @@ to_tsquery('english', 'state') --is that column in posts15 table?
)
SELECT cte_posts.*, urls.image_url as url_image_url
FROM cte_posts
join vision2.organizations on organizations.id = cte_posts.id
left join vision2.urls on urls.id = cte_posts.url_id
      --you could try moving this WHERE to CTE as well, depending on your data
where string_to_array(upper(organizations.irs_state), '') && array['NJ']
order by cte_posts.created desc
offset 0
limit 40

请注意,该表中的单个行是廉价的0.013ms,但该表上有870k个循环。您是否尝试过在您创建的日期和/或块上创建索引?请注意,在计划的上面几层上,行大小相当大~1K。散列表可能会溢出到磁盘。顺便说一句:请将您的查询编辑为可读的内容……您能再次检查您发布的查询是否与执行计划一致吗?有些东西不匹配,例如,执行计划中没有分区\日期筛选器,但它们在where子句中,执行计划中的解析器正在查找educ,而查询显示“英语”、“状态”。无论如何,我的直觉是,查询并没有绑定到SELECT4执行计划。执行计划实际上看起来可能在posts表上存在两次恶意连接。