Postgres10高性能開發(5)高級SQL

WITH CTE公用表達式查詢

  • https://www.postgresql.org/docs/10/queries-with.html
  • https://www.postgresql.org/docs/10/sql-select.html

WITH提供了一種編寫輔助語句以便在更大的查詢中使用的方法。這些語句(通常稱爲公用表表達式或CTE)可以被視爲定義僅針對一個查詢存在的臨時表。一個在每個輔助語句WITH子句可以是SELECT,INSERT,UPDATE,或DELETE; 和WITH本身所在的主語句也可以是SELECT,INSERT,UPDATE,或DELETE

  • WITH子句可以將在SQL中多次出現的SQL語句提取出來,簡化SQL編寫
  • WITH子句無論使用多少次,都只會計算一次
    • 優點:性能比計算多次更好
    • 缺點:如果主句中有其他限制條件可以大幅加快表查找數據,使用WITH子句,在子句將無法使用該限制
WITH invoice_by_type AS ( SELECT cl_invoice_type, COUNT ( 1 ) COUNT FROM inv_t_invoice GROUP BY cl_invoice_type ),
invoice_max_type AS ( SELECT cl_invoice_type FROM invoice_by_type ORDER BY COUNT DESC LIMIT 2 ) 
SELECT
i.cl_id,i.cl_invoice_type,T.count
FROM
	inv_t_invoice i
	LEFT JOIN invoice_by_type T ON i.cl_invoice_type = T.cl_invoice_type 
WHERE
	i.cl_invoice_type IN (
SELECT
	cl_invoice_type 
FROM
	invoice_max_type)
  • 有兩個With子句invoice_by_type和invoice_max_type ,其中invoice_max_type用到了子句invoice_by_type

RECURSIVE

遞歸語法

非遞歸語句 UNION [ ALL | DISTINCT ] 遞歸語句
  • 遞歸自引用必須出現在右側UNION
  • 每個查詢只允許一次遞歸自引用
  • 不支持遞歸數據修改語句

例如

WITH RECURSIVE t(n) AS (
    VALUES (1)
  UNION ALL
    SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;

遞歸計算執行過程

  1. 計算非遞歸語句,如果是UNION則先去重,將數據放入最終結果表和臨時表中
  2. 執行遞歸語句訪問臨時表進行查詢,如果是UNION則和最終結果表去重,將數據追加到最終結果表,覆蓋臨時表
  3. 如果臨時表爲空,則中斷遞歸,否則返回第2步

需要注意防止遞歸出現無限循環,可以在主語句加入limit防止死循環

刪除並轉移數據

刪除products數據並移到products_log

WITH moved_rows AS(
    DELETE FROM products 
    WHERE 
        “date”> ='2010-10-01'and 
        “date”<'2010-11-01'RETURNING 
    * 
)
INSERT INTO products_log 
SELECT * FROM moved_rows;

同時刪除兩張表數據,返回的影響行數是bar錶行數

WITH t AS(
    DELETE FROM foo 
)
DELETE FROM bar;

強制主句在WITH子句後執行

如果主句沒有使用WITH子句,主句和子句的執行順序無法確定

WITH t AS (
    UPDATE products SET price = price * 1.05
    RETURNING *
)
SELECT * FROM products;

可通過RETURNING *強制在主句中使用WITH子句,實現先執行用WITH子句,再執行主句

WITH t AS (
    UPDATE products SET price = price * 1.05
    RETURNING *
)
SELECT * FROM t;

CLUSTER聚類表

https://www.postgresql.org/docs/10/sql-cluster.html

將當前錶轉爲索引聚類表,索引聚類表將數據和索引存儲在一起,可以加快通過索引訪問數據的速度

使用指定索引聚類表

CLUSTER [VERBOSE] table_name [ USING index_name ]

聚類所有表

CLUSTER [VERBOSE] 

索引聚類表不能在事物中執行

  • 如果有新增行,新行不會按索引排序
  • 如果原連續存儲空間不足,更新行可能也不會按索引排序

可以通過命令重建索引聚類表,保障所有行按索引順序

Window Functions

https://www.postgresql.org/docs/10/tutorial-window.html

取得員工部門,員工編號,本部門平均工資

SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM empsalary;

#Result
  depname  | empno | salary |          avg          
-----------+-------+--------+-----------------------
 develop   |    11 |   5200 | 5020.0000000000000000
 develop   |     7 |   4200 | 5020.0000000000000000
 develop   |     9 |   4500 | 5020.0000000000000000
 develop   |     8 |   6000 | 5020.0000000000000000
 develop   |    10 |   5200 | 5020.0000000000000000
 personnel |     5 |   3500 | 3700.0000000000000000
 personnel |     2 |   3900 | 3700.0000000000000000
 sales     |     3 |   4800 | 4866.6666666666666667
 sales     |     1 |   5000 | 4866.6666666666666667
 sales     |     4 |   4800 | 4866.6666666666666667
(10 rows)

取得員工部門,員工編號,薪資,部門內薪資排名

SELECT depname, empno, salary,
       rank() OVER (PARTITION BY depname ORDER BY salary DESC)
FROM empsalary;

並行查詢

並行查詢允許一個SQL同時使用多個CPU加快查詢速度,主要用於OLAP場景

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章