濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > PostgreSQL利用遞歸優(yōu)化求稀疏列唯一值的方法

PostgreSQL利用遞歸優(yōu)化求稀疏列唯一值的方法

熱門(mén)標(biāo)簽:電話機(jī)器人怎么換人工座席 移動(dòng)外呼系統(tǒng)模擬題 地圖標(biāo)注要花多少錢(qián) 天津開(kāi)發(fā)區(qū)地圖標(biāo)注app 廣州電銷機(jī)器人公司招聘 濟(jì)南外呼網(wǎng)絡(luò)電話線路 電銷機(jī)器人能補(bǔ)救房產(chǎn)中介嗎 400電話申請(qǐng)客服 江蘇400電話辦理官方

在數(shù)據(jù)庫(kù)中經(jīng)常會(huì)碰到一些表的列是稀疏列,只有很少的值,例如性別字段,一般就只有2種不同的值。
但是當(dāng)我們求這些稀疏列的唯一值時(shí),如果表的數(shù)據(jù)量很大,速度還是會(huì)很慢。

例如:
創(chuàng)建測(cè)試表

bill=# create table t_sex (sex char(1), otherinfo text);
CREATE TABLE
bill=# insert into t_sex select 'm', generate_series(1,10000000)||'this is test';
INSERT 0 10000000
bill=# insert into t_sex select 'w', generate_series(1,10000000)||'this is test';
INSERT 0 10000000

查詢:
可以看到下面的查詢速度很慢。

bill=# select count(distinct sex) from t_sex;
 count
-------
   2
(1 row)

Time: 8803.505 ms (00:08.804)
bill=# select sex from t_sex t group by sex;
 sex
-----
 m
 w
(2 rows)

Time: 1026.464 ms (00:01.026)

那么我們對(duì)該字段加上索引又是什么情況呢?

速度依然沒(méi)有明顯

bill=# create index idx_sex_1 on t_sex(sex);
CREATE INDEX
bill=# select count(distinct sex) from t_sex;
 count
-------
   2
(1 row)

Time: 8502.460 ms (00:08.502)
bill=# select sex from t_sex t group by sex;
 sex
-----
 m
 w
(2 rows)

Time: 572.353 ms

的變化,可以看到執(zhí)行計(jì)劃已經(jīng)使用Index Only Scan了。

bill=# explain select count(distinct sex) from t_sex;
                     QUERY PLAN
----------------------------------------------------------------------------------------------
 Aggregate (cost=371996.44..371996.45 rows=1 width=8)
  -> Index Only Scan using idx_sex_1 on t_sex (cost=0.44..321996.44 rows=20000000 width=2)
(2 rows)

同樣的SQL我們看看在Oracle中性能如何?

創(chuàng)建測(cè)試表:

SQL> create table t_sex (sex char(1), otherinfo varchar2(100));

Table created.

SQL> insert into t_sex select 'm', rownum||'this is test' from dual connect by level =10000000;

10000000 rows created.

SQL> commit;

Commit complete.

SQL> insert into t_sex select 'w', rownum||'this is test' from dual connect by level =10000000;

10000000 rows created.

SQL> commit;

Commit complete.

性能測(cè)試:

SQL> set lines 1000 pages 2000
SQL> set autotrace on
SQL> set timing on

SQL> select count(distinct sex) from t_sex;

COUNT(DISTINCTSEX)
------------------
         2

Elapsed: 00:00:01.58

Execution Plan
----------------------------------------------------------
Plan hash value: 3915432945

----------------------------------------------------------------------------
| Id | Operation     | Name | Rows | Bytes | Cost (%CPU)| Time   |
----------------------------------------------------------------------------
|  0 | SELECT STATEMENT  |    |   1 |   3 | 20132  (1)| 00:00:01 |
|  1 | SORT GROUP BY   |    |   1 |   3 |      |     |
|  2 |  TABLE ACCESS FULL| T_SEX |  14M|  42M| 20132  (1)| 00:00:01 |
----------------------------------------------------------------------------

Note
-----
  - dynamic statistics used: dynamic sampling (level=2)


Statistics
----------------------------------------------------------
     0 recursive calls
     0 db block gets
   74074 consistent gets
     0 physical reads
     0 redo size
    552 bytes sent via SQL*Net to client
    608 bytes received via SQL*Net from client
     2 SQL*Net roundtrips to/from client
     1 sorts (memory)
     0 sorts (disk)
     1 rows processed

SQL> select sex from t_sex t group by sex;

SE
--
m
w

Elapsed: 00:00:01.08

Execution Plan
----------------------------------------------------------
Plan hash value: 3915432945

----------------------------------------------------------------------------
| Id | Operation     | Name | Rows | Bytes | Cost (%CPU)| Time   |
----------------------------------------------------------------------------
|  0 | SELECT STATEMENT  |    |  14M|  42M| 20558  (3)| 00:00:01 |
|  1 | SORT GROUP BY   |    |  14M|  42M| 20558  (3)| 00:00:01 |
|  2 |  TABLE ACCESS FULL| T_SEX |  14M|  42M| 20132  (1)| 00:00:01 |
----------------------------------------------------------------------------

Note
-----
  - dynamic statistics used: dynamic sampling (level=2)


Statistics
----------------------------------------------------------
     0 recursive calls
     0 db block gets
   74074 consistent gets
     0 physical reads
     0 redo size
    589 bytes sent via SQL*Net to client
    608 bytes received via SQL*Net from client
     2 SQL*Net roundtrips to/from client
     1 sorts (memory)
     0 sorts (disk)
     2 rows processed

可以看到Oracle的性能即使不加索引也明顯比PostgreSQL中要好。
那么我們?cè)赑ostgreSQL中是不是沒(méi)辦法繼續(xù)優(yōu)化了呢?這種情況我們利用pg中的遞歸語(yǔ)句結(jié)合索引可以大幅提升性能。

SQL改寫(xiě):

bill=# with recursive tmp as (
bill(#  (
bill(#   select min(t.sex) as sex from t_sex t where t.sex is not null
bill(#  )
bill(#  union all
bill(#  (
bill(#   select (select min(t.sex) from t_sex t where t.sex > s.sex and t.sex is not null)
bill(#    from tmp s where s.sex is not null
bill(#  )
bill(# )
bill-# select count(distinct sex) from tmp;
 count
-------
   2
(1 row)

Time: 2.711 ms

查看執(zhí)行計(jì)劃:

bill=# explain with recursive tmp as (
bill(#  (
bill(#   select min(t.sex) as sex from t_sex t where t.sex is not null
bill(#  )
bill(#  union all
bill(#  (
bill(#   select (select min(t.sex) from t_sex t where t.sex > s.sex and t.sex is not null)
bill(#    from tmp s where s.sex is not null
bill(#  )
bill(# )
bill-# select count(distinct sex) from tmp;
                           QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
 Aggregate (cost=53.62..53.63 rows=1 width=8)
  CTE tmp
   -> Recursive Union (cost=0.46..51.35 rows=101 width=32)
      -> Result (cost=0.46..0.47 rows=1 width=32)
         InitPlan 3 (returns $1)
          -> Limit (cost=0.44..0.46 rows=1 width=2)
             -> Index Only Scan using idx_sex_1 on t_sex t (cost=0.44..371996.44 rows=20000000 width=2)
                Index Cond: (sex IS NOT NULL)
      -> WorkTable Scan on tmp s (cost=0.00..4.89 rows=10 width=32)
         Filter: (sex IS NOT NULL)
  -> CTE Scan on tmp (cost=0.00..2.02 rows=101 width=32)
(11 rows)

Time: 1.371 ms

可以看到執(zhí)行時(shí)間從原先的8000ms降低到了2ms,提升了幾千倍!

甚至對(duì)比Oracle,性能也是提升了很多。

但是需要注意的是:這種寫(xiě)法僅僅是針對(duì)稀疏列,換成數(shù)據(jù)分布廣泛的字段,顯然性能是下降的, 所以使用遞歸SQL不適合數(shù)據(jù)分布廣泛的字段的group by或者count(distinct)操作。

到此這篇關(guān)于PostgreSQL利用遞歸優(yōu)化求稀疏列唯一值的文章就介紹到這了,更多相關(guān)PostgreSQL遞歸優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • postgresql 導(dǎo)入數(shù)據(jù)庫(kù)表并重設(shè)自增屬性的操作
  • 在PostgreSQL中設(shè)置表中某列值自增或循環(huán)方式
  • postgresql數(shù)據(jù)添加兩個(gè)字段聯(lián)合唯一的操作

標(biāo)簽:榆林 昭通 溫州 海西 辛集 濮陽(yáng) 杭州 寶雞

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PostgreSQL利用遞歸優(yōu)化求稀疏列唯一值的方法》,本文關(guān)鍵詞  PostgreSQL,利用,遞歸,優(yōu)化,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《PostgreSQL利用遞歸優(yōu)化求稀疏列唯一值的方法》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于PostgreSQL利用遞歸優(yōu)化求稀疏列唯一值的方法的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    滕州市| 昭觉县| 离岛区| 宝山区| 汉沽区| 响水县| 大渡口区| 筠连县| 鲁山县| 武城县| 犍为县| 卓尼县| 中阳县| 济阳县| 广汉市| 泸溪县| 枝江市| 恩施市| 安远县| 纳雍县| 长寿区| 南郑县| 冀州市| 布尔津县| 临朐县| 分宜县| 广丰县| 武汉市| 新蔡县| 宝山区| 杭锦旗| 神池县| 灵台县| 合川市| 汝州市| 北辰区| 丰台区| 柳江县| 辽源市| 资中县| 临沧市|