PostgreSQL 中的优化查询

Posted

技术标签:

【中文标题】PostgreSQL 中的优化查询【英文标题】:Optimized querying in PostgreSQL 【发布时间】:2015-04-02 13:19:36 【问题描述】:

假设您有一个名为 tracker 的表,其中包含以下记录。

issue_id  |  ingest_date         |  verb,status
10         2015-01-24 00:00:00    1,1
10         2015-01-25 00:00:00    2,2
10         2015-01-26 00:00:00    2,3
10         2015-01-27 00:00:00    3,4
11         2015-01-10 00:00:00    1,3
11         2015-01-11 00:00:00    2,4

我需要以下结果

10         2015-01-26 00:00:00    2,3
11         2015-01-11 00:00:00    2,4

我正在尝试这个查询

select * 
from etl_change_fact 
where ingest_date = (select max(ingest_date) 
                     from etl_change_fact);

但是,这只给了我

10    2015-01-26 00:00:00    2,3

这条记录。

但是,我希望所有唯一记录(change_id)都带有

(a) max(ingest_date) 与

(b) 动词列优先级为(2 - 第一个首选,1 - 第二个首选,3 - 最后一个首选)

因此,我需要以下结果

10    2015-01-26 00:00:00    2,3
11    2015-01-11 00:00:00    2,4

请帮我高效查询。

附注: 我不会索引 ingest_date,因为我将在分布式计算设置中将其设置为“分发密钥”。 我是数据仓库和查询的新手。

因此,请帮助我以优化方式访问我的 TB 大小的数据库。

【问题讨论】:

我不明白这个问题。 max(ingest_date) 是“2015-01-26 00:00:00”,所以条件 a) 只会让您获得该记录。你的条件(b)是什么意思?你能改写一下吗,因为我不明白你的描述与你想要返回的记录有什么关系。最后——mysql还是postgresql? 我需要postgreSQL @mlinth :我的两个条件都有效......!请查看我的示例数据...相比之下,如果我取 max(ingest_date) 并且记录的动词为 3,我不想要该记录。我想要它之前的那个(我的意思是没有动词 3) 【参考方案1】:

这是一个典型的“greatest-n-per-group”问题。如果你在这里搜索这个标签,你会得到很多解决方案——包括 MySQL。

对于 Postgres,最快的方法是使用 distinct on(这是 SQL 语言的 Postgres 专有扩展)

select distinct on (issue_id) issue_id, ingest_date, verb, status
from etl_change_fact
order by issue_id, 
         case verb 
            when 2 then 1 
            when 1 then 2
            else 3
         end, ingest_date desc;

您可以增强原始查询以使用相关的子查询来实现相同的目的:

select f1.* 
from etl_change_fact f1
where f1.ingest_date = (select max(f2.ingest_date) 
                        from etl_change_fact f2
                        where f1.issue_id = f2.issue_id);

编辑

对于过时且不受支持的 Postgres 版本,您可能可以使用这样的方法逃脱:

select f1.* 
from etl_change_fact f1
where f1.ingest_date = (select f2.ingest_date
                        from etl_change_fact f2
                        where f1.issue_id = f2.issue_id
                        order by case verb 
                                  when 2 then 1 
                                  when 1 then 2
                                  else 3
                              end, ingest_date desc
                        limit 1);

SQLFiddle 示例:http://sqlfiddle.com/#!15/3bb05/1

【讨论】:

谢谢马...除了摄取日期条件外,我还想添加“动词”条件....如果可以请帮助... ERROR: SELECT DISTINCT ON is not supported getting this error... 我的 postgreSQL 版本是 8.0.2 @user2893206: 8.0 已经超过 5 年没有维护了,已经 10 岁了。您要做的第一件事是升级到受支持的当前版本(例如 9.4)。 对不起。我明白。我实际上的意思是“如果您有任何想法,请帮助我” 谢谢。但是,上面的查询给了我所有的记录。

以上是关于PostgreSQL 中的优化查询的主要内容,如果未能解决你的问题,请参考以下文章

针对多个表优化缓慢的 postgresql 查询

连接postgres特别消耗cpu资源而引发的PostgreSQL性能优化考虑

如何优化 Postgresql max_connections 和 node-postgres 连接池?

Postgres 中的慢查询优化

连接postgres特别消耗cpu资源而引发的PostgreSQL性能优化考虑

优化 Postgres 中的 case/decode 查询