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
)
|
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版本測試的結果。