KingbaseES不同字符類型比較轉換規則


Postgresql 常用的字符數據類型的有char、varchar和text,其中 char 固定長度類型, varchar 和 text 是可變長度類型。這三種類型在進行比較時,會進行隱含的類型轉換。這種轉換會導致索引可能無法使用,影響SQL的執行計划。以下以例子的形式展示Postgresql 不同字符數據類型間的轉換規則。

一、創建測試數據

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create  table  test_char(id  char (9),desc_info text);
create  table  test_varchar(id  varchar (9),desc_info text);
create  table  test_text(id text,desc_info text);
insert  into  test_char  select  generate_series(100001,200000),repeat( 'a' ,100);
insert  into  test_varchar  select  generate_series(100001,200000),repeat( 'a' ,100);
insert  into  test_text  select  generate_series(100001,200000),repeat( 'a' ,100);
create  index  ind_test_char  on  test_char(id);
create  index  ind_test_varchar  on  test_varchar(id);
create  index  ind_test_text  on  test_text(id);
analyze test_char;
analyze test_varchar;
analyze test_text;

二、創建SQL游標

1
2
3
4
5
6
7
8
prepare  test_char_bind_varchar( varchar as  select  from  test_char  where  id=$1;
prepare  test_char_bind_text(text)  as  select  from  test_char  where  id=$1;
prepare  test_varchar_bind_char( char as  select  from  test_varchar  where  id=$1;
prepare  test_text_bind_char( char as  select  from  test_text  where  id=$1;
prepare  test_varchar_bind_text(text)  as  select  from  test_varchar  where  id=$1;
prepare  test_text_bind_varchar( varchar as  select  from  test_text  where  id=$1;

三、Postgresql字符類型的隱含轉換規則

1、對於 varchar 與 char 比較,默認是 varchar 轉成 char。

例子2,由於等式左邊發生了類型轉換,無法使用索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
例子1:
testdb=# explain  execute  test_char_bind_varchar( '123456' );
                                    QUERY PLAN                                   
---------------------------------------------------------------------------------
  Index  Scan using ind_test_char  on  test_char  (cost=0.42..8.44  rows =1 width=111)
    Index  Cond: (id =  '123456' ::bpchar)
(2  rows )
例子2:等式左邊發生類型轉換,無法使用索引
testdb=# explain  execute  test_varchar_bind_char( '123456' );
                            QUERY PLAN                           
-----------------------------------------------------------------
  Seq Scan  on  test_varchar  (cost=0.00..2975.00  rows =1 width=108)
    Filter: ((id)::bpchar =  '123456' ::bpchar)
(2  rows )

2、對於 text 與 char 比較,默認是 char 轉成 text 。

例子3,由於等式左邊發生了類型轉換,無法使用索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
例子3:等式左邊發生類型轉換,無法使用索引。
testdb=# explain  execute  test_char_bind_text( '123456' );
                            QUERY PLAN                          
----------------------------------------------------------------
  Seq Scan  on  test_char  (cost=0.00..3225.00  rows =500 width=111)
    Filter: ((id)::text =  '123456' ::text)
(2  rows )
例子4:
testdb=# explain  execute  test_text_bind_char( '123456' );
                                    QUERY PLAN                                   
---------------------------------------------------------------------------------
  Index  Scan using ind_test_text  on  test_text  (cost=0.29..8.31  rows =1 width=108)
    Index  Cond: (id =  '123456' ::text)
(2  rows )

3、對於 varchar 與 text 比較,默認是 varchar 轉成 text ,但二者的轉換不影響索引的使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
testdb=# explain  execute  test_varchar_bind_text( '123456' );
                                       QUERY PLAN                                      
---------------------------------------------------------------------------------------
  Index  Scan using ind_test_varchar  on  test_varchar  (cost=0.29..8.31  rows =1 width=108)
    Index  Cond: ((id)::text =  '123456' ::text)
(2  rows )
testdb=# explain  execute  test_text_bind_varchar( '123456' );
                                    QUERY PLAN                                   
---------------------------------------------------------------------------------
  Index  Scan using ind_test_text  on  test_text  (cost=0.29..8.31  rows =1 width=108)
    Index  Cond: (id =  '123456' ::text)
(2  rows )

PG 字符類型數據轉換規則:varchar -> char -> text

四、KingbaseES 類型轉換及優化

用過Oracle的人都知道,char與varchar 之間的比較不會因為類型不同而無法使用索引,Kingbase在特性上向Oracle靠攏,為用戶從Oracle向KingbaseES遷移提供便利。KingbaseES 繼承Postgresql 的特性,同時通過代碼的優化,避免了char與varchar和text之間比較導致的轉換而無法使用索引的情況。以下的例子在KingbaseES V8R6 版本進行過實際驗證。

1、對於 varchar 與 char 比較,同樣是 varchar 轉成 char。

kingbase 針對這個問題,進行了特殊的優化處理,即使等式左邊的varchar發生了類型轉換,也不影響索引的使用,如:例子6。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
例子5:
testdb=# explain  execute  test_char_bind_varchar( '123456' );
                                    QUERY PLAN                                   
---------------------------------------------------------------------------------
  Index  Scan using ind_test_char  on  test_char  (cost=0.42..8.44  rows =1 width=111)
    Index  Cond: (id =  '123456' ::bpchar)
(2  rows )
例子6:不會因為等式左邊發生類型轉換而無法使用索引。
testdb=# explain  execute  test_varchar_bind_char( '123456' );
                                       QUERY PLAN                                      
---------------------------------------------------------------------------------------
  Index  Scan using ind_test_varchar  on  test_varchar  (cost=0.29..8.31  rows =1 width=108)
    Index  Cond: ((id)::text =  '123456' ::text)
(2  rows )

2、對於 text 與 char 比較,kingbase 進行了特殊的優化處理,使得轉換發生在等式的右邊,不影響索引的使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
例子7:
testdb=# explain  execute  test_char_bind_text( '123456' );
                                    QUERY PLAN                                   
---------------------------------------------------------------------------------
  Index  Scan using ind_test_char  on  test_char  (cost=0.42..8.44  rows =1 width=111)
    Index  Cond: (id =  '123456' ::bpchar)
(2  rows )
例子8:
testdb=# explain  execute  test_text_bind_char( '123456' );
                                    QUERY PLAN                                   
---------------------------------------------------------------------------------
  Index  Scan using ind_test_text  on  test_text  (cost=0.29..8.31  rows =1 width=108)
    Index  Cond: (id =  '123456' ::text)
(2  rows )

3、對於 varchar 與 text 比較,默認是 varchar 轉成 text 。與PG一樣,二者的轉換不影響索引的使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
test=# explain  execute  test_varchar_bind_text( '123456' );
                                       QUERY PLAN                                      
---------------------------------------------------------------------------------------
  Index  Scan using ind_test_varchar  on  test_varchar  (cost=0.29..8.31  rows =1 width=108)
    Index  Cond: ((id)::text =  '123456' ::text)
(2  rows )
test=# explain  execute  test_text_bind_varchar( '123456' );
                                    QUERY PLAN                                   
---------------------------------------------------------------------------------
  Index  Scan using ind_test_text  on  test_text  (cost=0.29..8.31  rows =1 width=108)
    Index  Cond: (id =  '123456' ::text)
(2  rows )

 

Tips:以上例子是基於Postgresql 12.3 和 KingbaseES V8R6版本測試的結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM