postgres 如何处理对某些列具有假值的视图的查询?

Posted

技术标签:

【中文标题】postgres 如何处理对某些列具有假值的视图的查询?【英文标题】:How postgres process a query on a view with fake values for some columns? 【发布时间】:2019-07-25 09:04:45 【问题描述】:

3 个表格和 1 个视图 查询将如何使用假的“null as col”值?

Table1
- IndexedCol1 
- Col2
- CommonIndexedCol1
- CommonIndexedCol2
- CommonIndexedCol3

Table2
- IndexedCol2 
- Col3
- Col4
- CommonIndexedCol1
- CommonIndexedCol2
- CommonIndexedCol3

Table3
- IndexedCol3 
- Col5
- Col6
- CommonIndexedCol1
- CommonIndexedCol2
- CommonIndexedCol3


View1
- Table1.IndexedCol1
- Table2.IndexedCol2
- Table3.IndexedCol3
- CommonIndexedCol1
- CommonIndexedCol2
- CommonIndexedCol3

View1 查询是:

SELECT IndexedCol1, null as IndexedCol2, null as IndexedCol3, CommonIndexedCol1, CommonIndexedCol2, CommonIndexedCol3 FROM Table1
UNION
SELECT null as IndexedCol1, IndexedCol2, null as IndexedCol3, CommonIndexedCol1, CommonIndexedCol2, CommonIndexedCol3 FROM Table2
UNION
SELECT null as IndexedCol1, null as IndexedCol2, IndexedCol3, CommonIndexedCol1, CommonIndexedCol2, CommonIndexedCol3 FROM Table3

假设每个表有 100 万行

如果我运行以下查询

SELECT * FROM View1 WHERE CommonIndexedCol1=1 AND IndexedCol1 is NOT NULL

postgres 是否会跳过具有 SELECT(null as IndexedCol1)的选择,因此仅查询 1 个表,仅 100 万行,它是否理解此选择将导致所有空值,因此它应该跳过第二个和第三个选择查询开始? 或者它会查询 3 个表中的全部 300 万条记录是否为非空 IndexedCol1?

【问题讨论】:

PostgreSQL 支持EXPLAIN 告诉你它将如何处理查询.. 运行explain (analyze) select ...,你会看到Postgres会做什么 @a_horse_with_no_name 是的,问题中的拼写错误,已修复...我现在就写EXPLAIN,谢谢 【参考方案1】:

postgres 如何处理对某些列的假值视图的查询?

PostgreSQL 优化器应该将 WHERE 子句从在 VIEW 上进行的查询下推到 VIEW 查询定义。

换句话说,PostgreSQL 上的 VIEW 处理/处理优化就像 SQL“预处理器”或模板系统一样工作。

查询

SELECT * 
FROM View1 
WHERE CommonIndexedCol1 = 1 AND IndexedCol1 is NOT NULL

会改写成

SELECT *
FROM 
    (SELECT
         IndexedCol1
         , null as IndexedCol2
         , null as IndexedCol3
         , CommonIndexedCol1
         , CommonIndexedCol2
         , CommonIndexedCol3
     FROM 
         Table1
     WHERE 
         CommonIndexedCol1 = 1 AND IndexedCol1 IS NOT NULL
   UNION
   SELECT
      null as IndexedCol1
    , IndexedCol2
    , null as IndexedCol3
    , CommonIndexedCol1, CommonIndexedCol2, CommonIndexedCol3
   FROM Table2
   WHERE CommonIndexedCol1=1 AND IndexedCol1 is NOT NULL
   UNION
    SELECT
       null as IndexedCol1
     , null as IndexedCol2
     , IndexedCol3
     , CommonIndexedCol1
     , CommonIndexedCol2
     , CommonIndexedCol3
   FROM Table3
   WHERE CommonIndexedCol1=1 AND IndexedCol1 is NOT NULL
 ) AS View1

经过更多优化(扁平化)

   SELECT
       IndexedCol1
     , null as IndexedCol2
     , null as IndexedCol3
     , CommonIndexedCol1
     , CommonIndexedCol2
     , CommonIndexedCol3
   FROM Table1
   WHERE CommonIndexedCol1=1 AND IndexedCol1 is NOT NULL
   UNION
   SELECT
      null as IndexedCol1
    , IndexedCol2
    , null as IndexedCol3
    , CommonIndexedCol1, CommonIndexedCol2, CommonIndexedCol3
   FROM Table2
   WHERE CommonIndexedCol1=1 AND IndexedCol1 is NOT NULL
   UNION
    SELECT
       null as IndexedCol1
     , null as IndexedCol2
     , IndexedCol3
     , CommonIndexedCol1
     , CommonIndexedCol2
     , CommonIndexedCol3
   FROM Table3
   WHERE CommonIndexedCol1=1 AND IndexedCol1 is NOT NULL

如果你想跑

EXPLAIN SELECT * FROM View1 WHERE CommonIndexedCol1=1 AND IndexedCol1 is NOT NULL

您应该看到 Table1、Table2 和 Table3,并且在说明中没有提到 View1..

【讨论】:

以上是关于postgres 如何处理对某些列具有假值的视图的查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理对 UITableView 的非单元格区域的点击

WPF 如何处理对空对象属性的绑定?

Falcor 模型如何处理对字符串的引用?

在设计数据库时,存储多个真/假值的首选方式是啥?

如何处理对客户端反应应用程序的外部重定向?

c#:如何处理对对象进行深度拷贝