PG 優化器的精彩
我們先看下面sql:[code]
postgres=# SELECT
postgres-# (
postgres(# SELECT string_agg(x, '')
postgres(# FROM (
postgres(# SELECT chr(ascii('a') + floor(random() * 26)::integer)
postgres(# FROM generate_series(1, 40 + b * 0) as f(g)
postgres(# ) AS y(x)
postgres(# ) AS result
postgres-# FROM generate_series(1,5) as a(b);
result
------------------------------------------
oltxgwlsjdueshyjeiydcasfslbnpjzevsbcpnuz
rpdjxcsbkrfnrytkjvxzfweapgcftxelnhulknmv
esiwrchbxeacbfdqlfwfdaqqilbsyondhwayyhzw
maynfberhaxkaobjzdbysobzlcyjkyfwyejegowo
ptzphazgeaewpgwaivkttqpruzwbnspcmostprau
(5 DD????)
postgres=# SELECT
(
SELECT string_agg(x, '')
FROM (
SELECT chr(ascii('a') + floor(random() * 26)::integer)
FROM generate_series(1, 40 ) as f(g)
) AS y(x)
) AS result
FROM generate_series(1,5) as a(b);
result
------------------------------------------
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
[/code]上面的sql 返回了5筆長度為40的隨機的字串。
下面的sql 返回了5筆重複的字串。 在我們的印象裡,b*0 =0 40+0 =40 加與不加結果應該是一樣的。
實際上卻相差很遠。
從下面的sql 看似乎裡面的隨機數random() 只執行了一次,或者說是快取了結果集,導致外面的序列,重複的輸出了5次。
我們看看他們的執行計劃:[code]
postgres=# explain SELECT
postgres-# (
postgres(# SELECT string_agg(x, '')
postgres(# FROM (
postgres(# SELECT chr(ascii('a') + floor(random() * 26)::integer)
postgres(# FROM generate_series(1, 40 + b * 0) as f(g)
postgres(# ) AS y(x)
postgres(# ) AS result
postgres-# FROM generate_series(1,5) as a(b);
QUERY PLAN
----------------------------------------------------------------------------------------
Function Scan on generate_series a (cost=0.00..37530.00 rows=1000 width=4)
SubPlan 1
-> Aggregate (cost=37.51..37.52 rows=1 width=32)
-> Function Scan on generate_series f (cost=0.01..25.01 rows=1000 width=0)
(4 DD????)
postgres=#
explain SELECT
(
SELECT string_agg(x, '')
FROM (
SELECT chr(ascii('a') + floor(random() * 26)::integer)
FROM generate_series(1, 40 ) as f(g)
) AS y(x)
) AS result
FROM generate_series(1,5) as a(b);
QUERY PLAN
----------------------------------------------------------------------------------------
Function Scan on generate_series a (cost=37.52..47.52 rows=1000 width=0)
InitPlan 1 (returns $0)
-> Aggregate (cost=37.50..37.51 rows=1 width=32)
-> Function Scan on generate_series f (cost=0.00..25.00 rows=1000 width=0)
(4 DD????)
[/code]兩個sql 的執行計劃是不同的。
pg的優化器 認為第二個sql 中,裡面的subquery 是不依賴於外面的sql,所以優化器對他進行了評估計算固定為initplain
這個時候,跟裡面的函式random 的volatile 跟stable 屬性是無關的。
這就要引入pg的函式或者表示式的volatile 很stable 屬性了
所謂的volatile 就是不穩定,即這個函式對同一個輸入,可能產生不同的輸出。
而對於第一個sql ,subquery 應用到了外面sql的變數,導致針對外面sql的每一行都要計算裡面的subquery。
我們修改為每次輸出100調記錄, 第二個sql 用時0.77ms 第一個sql用4.13 ms
也可以看出第一個sql做了更多的活。
針對 函式的volatile 和stable 的屬性,再準備下開新帖說明啦,今天到這裡了。
postgres=# SELECT
postgres-# (
postgres(# SELECT string_agg(x, '')
postgres(# FROM (
postgres(# SELECT chr(ascii('a') + floor(random() * 26)::integer)
postgres(# FROM generate_series(1, 40 + b * 0) as f(g)
postgres(# ) AS y(x)
postgres(# ) AS result
postgres-# FROM generate_series(1,5) as a(b);
result
------------------------------------------
oltxgwlsjdueshyjeiydcasfslbnpjzevsbcpnuz
rpdjxcsbkrfnrytkjvxzfweapgcftxelnhulknmv
esiwrchbxeacbfdqlfwfdaqqilbsyondhwayyhzw
maynfberhaxkaobjzdbysobzlcyjkyfwyejegowo
ptzphazgeaewpgwaivkttqpruzwbnspcmostprau
(5 DD????)
postgres=# SELECT
(
SELECT string_agg(x, '')
FROM (
SELECT chr(ascii('a') + floor(random() * 26)::integer)
FROM generate_series(1, 40 ) as f(g)
) AS y(x)
) AS result
FROM generate_series(1,5) as a(b);
result
------------------------------------------
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
sfrhmniujsncidudcqeqjutvjmpzeptwvlehymci
[/code]上面的sql 返回了5筆長度為40的隨機的字串。
下面的sql 返回了5筆重複的字串。 在我們的印象裡,b*0 =0 40+0 =40 加與不加結果應該是一樣的。
實際上卻相差很遠。
從下面的sql 看似乎裡面的隨機數random() 只執行了一次,或者說是快取了結果集,導致外面的序列,重複的輸出了5次。
我們看看他們的執行計劃:[code]
postgres=# explain SELECT
postgres-# (
postgres(# SELECT string_agg(x, '')
postgres(# FROM (
postgres(# SELECT chr(ascii('a') + floor(random() * 26)::integer)
postgres(# FROM generate_series(1, 40 + b * 0) as f(g)
postgres(# ) AS y(x)
postgres(# ) AS result
postgres-# FROM generate_series(1,5) as a(b);
QUERY PLAN
----------------------------------------------------------------------------------------
Function Scan on generate_series a (cost=0.00..37530.00 rows=1000 width=4)
SubPlan 1
-> Aggregate (cost=37.51..37.52 rows=1 width=32)
-> Function Scan on generate_series f (cost=0.01..25.01 rows=1000 width=0)
(4 DD????)
postgres=#
explain SELECT
(
SELECT string_agg(x, '')
FROM (
SELECT chr(ascii('a') + floor(random() * 26)::integer)
FROM generate_series(1, 40 ) as f(g)
) AS y(x)
) AS result
FROM generate_series(1,5) as a(b);
QUERY PLAN
----------------------------------------------------------------------------------------
Function Scan on generate_series a (cost=37.52..47.52 rows=1000 width=0)
InitPlan 1 (returns $0)
-> Aggregate (cost=37.50..37.51 rows=1 width=32)
-> Function Scan on generate_series f (cost=0.00..25.00 rows=1000 width=0)
(4 DD????)
[/code]兩個sql 的執行計劃是不同的。
pg的優化器 認為第二個sql 中,裡面的subquery 是不依賴於外面的sql,所以優化器對他進行了評估計算固定為initplain
這個時候,跟裡面的函式random 的volatile 跟stable 屬性是無關的。
這就要引入pg的函式或者表示式的volatile 很stable 屬性了
所謂的volatile 就是不穩定,即這個函式對同一個輸入,可能產生不同的輸出。
而對於第一個sql ,subquery 應用到了外面sql的變數,導致針對外面sql的每一行都要計算裡面的subquery。
我們修改為每次輸出100調記錄, 第二個sql 用時0.77ms 第一個sql用4.13 ms
也可以看出第一個sql做了更多的活。
針對 函式的volatile 和stable 的屬性,再準備下開新帖說明啦,今天到這裡了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/133735/viewspace-739657/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 優化PG查詢:一問一答優化
- oracle 的優化器Oracle優化
- Oracle的優化器Oracle優化
- 優化器優化
- 優化器的侷限優化
- 優化器提示優化
- Oracle資料的優化器有兩種優化方法:Oracle優化
- 優化器的發展程式優化
- PG 資料庫連線池寫法優化一例資料庫優化
- 【效能優化】CBO優化器兩個內建的假設優化
- 查詢優化器優化
- 【摘】 oracle優化器Oracle優化
- Mysql優化系列之——優化器對子查詢的處理MySql優化
- 給小白的 PG 容器化部署教程(下)
- MySQL查詢優化之優化器工作流程以及優化的執行計劃生成MySql優化
- 優化-瀏覽器快取和壓縮優化優化瀏覽器快取
- 前端效能優化之桌面瀏覽器優化策略前端優化瀏覽器
- 前端效能優化——桌面瀏覽器前端優化策略前端優化瀏覽器
- PostgreSQL10.0preview變化-pg_xlog,pg_clog,pg_log目錄更名為pg_wal,pg_xact,logSQLView
- 瀏覽器前端優化瀏覽器前端優化
- 【筆記】oracle 優化器筆記Oracle優化
- 共享儲存器優化優化
- HttpRunner 的結果校驗器優化HTTP優化
- KVM虛擬機器的效能優化虛擬機優化
- .選用適合的ORACLE優化器Oracle優化
- Oracle優化器的RBO和CBO方式Oracle優化
- Oracle的優化器的RBO和CBO方式Oracle優化
- MySQl 配置InnoDB持久化的優化器統計資訊MySql持久化優化
- PG資料庫初始化資料庫
- 前端效能優化 —— 移動端瀏覽器優化策略前端優化瀏覽器
- CUDA優化之執行配置和暫存器優化優化
- 【SQL優化器】初始化引數SQL優化
- [原始碼解析] PyTorch分散式優化器(2)----資料並行優化器原始碼PyTorch分散式優化並行
- 前端效能優化之移動端瀏覽器優化策略前端優化瀏覽器
- 利用Oracle 10g SQL優化器(STA)優化語句Oracle 10gSQL優化
- 影響ORACLE優化器的相關因素Oracle優化
- oracle優化器和不走索引的原因Oracle優化索引
- C++編譯器優化C++編譯優化