所以,我做了一些测试。
TL; DR
- 改国号列类型
CHAR(32)
,重建索引,你应该有更好的性能。
长的版本:
二手的Informix 12.10FC6DE在Linux CentOS的7(VM在VirtualBox中创建)。用于dbspace的页面大小为2048字节,缓冲池为50000页。
创建一个表格(tst),行大小约为425字节(每页平均4行),并包含多列。其中一列是country VARCHAR(32)
,另一列是static_country CHAR(32)
。 用499999行填充表格,其中列表country
和static_country
均匀分布为25个国家/地区名称。
创建了2个索引,其中一列在列country
(idx1_tst)和其他列static_country
(idx2_tst)上。
表分区使用了125000个数据页(使用oncheck -pT)。 索引大约有1500页(使用oncheck -pT)。
A.运行查询多次,迫使序列完备SCAN(运行时间分别为10和15秒之间):
SELECT --+ FULL (tst)
country, COUNT(*)
FROM
tst
GROUP BY
country
DIRECTIVES FOLLOWED:
FULL (tst)
DIRECTIVES NOT FOLLOWED:
Estimated Cost: 1415645
Estimated # of Rows Returned: 25
Temporary Files Required For: Group By
1) mydb.tst: SEQUENTIAL SCAN
Query statistics:
-----------------
Table map :
----------------------------
Internal name Table name
----------------------------
t1 tst
type table rows_prod est_rows rows_scan time est_cost
-------------------------------------------------------------------
scan t1 499999 499999 499999 00:12.17 140001
type rows_prod est_rows rows_cons time est_cost
------------------------------------------------------------
group 25 25 499999 00:13.01 1275644
B.运行查询多次,迫使索引扫描在country
列索引,它的类型的VARCHAR(32)(4m30s和5m之间的运行时间):
SELECT --+ INDEX (tst idx1_tst)
country, COUNT(*)
FROM
tst
GROUP BY
country
DIRECTIVES FOLLOWED:
INDEX (tst idx1_tst)
DIRECTIVES NOT FOLLOWED:
Estimated Cost: 3462411
Estimated # of Rows Returned: 25
1) mydb.tst: INDEX PATH
(1) Index Name: mydb.idx1_tst
Index Keys: country (Serial, fragments: ALL)
Query statistics:
-----------------
Table map :
----------------------------
Internal name Table name
----------------------------
t1 tst
type table rows_prod est_rows rows_scan time est_cost
-------------------------------------------------------------------
scan t1 499999 499999 499999 04:49.71 3462411
type rows_prod est_rows rows_cons time est_cost
------------------------------------------------------------
group 25 25 499999 04:50.51 1275644
C.运行查询几次,迫使一个索引扫描的static_country
列索引,它的类型CHAR(32)的(2和3秒之间的运行时间):
SELECT --+ INDEX (tst idx2_tst)
static_country, COUNT(*)
FROM
tst
GROUP BY
static_country
DIRECTIVES FOLLOWED:
INDEX (tst idx2_tst)
DIRECTIVES NOT FOLLOWED:
Estimated Cost: 16428
Estimated # of Rows Returned: 25
1) mydb.tst: INDEX PATH
(1) Index Name: mydb.idx2_tst
Index Keys: static_country (Key-Only) (Serial, fragments: ALL)
Query statistics:
-----------------
Table map :
----------------------------
Internal name Table name
----------------------------
t1 tst
type table rows_prod est_rows rows_scan time est_cost
-------------------------------------------------------------------
scan t1 499999 499999 499999 00:02.02 16429
type rows_prod est_rows rows_cons time est_cost
------------------------------------------------------------
group 25 25 499999 00:02.72 1277132
上的sysmaster使用SMI表sysptprof
数据库我可以看到以下计数器(使用运行之间onstat -z
重置计数器):
- 在情况A(序列完备SCAN):
- 表TST分区:
lockreqs 499999
isreads 125001
bufreads 500060
pagreads 117532
- 在情况B(在VARCHAR类型列INDEX SCAN):
- 表TST分区:
lockreqs 499999
isreads 499990
bufreads 999997
pagreads 348585
- 指数idx1_tst分区:
lockreqs 499999
isreads 500009
bufreads 506961
pagreads 2545
- 在情况C(在CHAR型柱INDEX SCAN):
- 指数idx2_tst分区:
lockreqs 499999
isreads 500000
bufreads 502879
pagreads 1440
因此,对于序列完备SCAN只有对表分区活动,如我所料。
对于CHAR列上的INDEX SCAN,索引分区上只有活动,正如我预期的那样(解释包含Key-Only
指示)。
对于VARCHAR colum上的INDEX SCAN,表和索引分区都有活动,而不是我所期望的(但正如费尔南多所指出的,解释不包含Key-Only
指示)。
我无法从informix解释这种行为。但是,一个同事向我指出的Informix的性能手册此条目(版本12.10FC6,第10章,查询计划,访问计划):
重要:优化器不会选择仅键扫描一VARCHAR 列。如果要利用仅键扫描,请使用带有MODIFY子句的ALTER TABLE将列更改为CHAR数据类型。
您使用的是11.10,11.50还是11.70版本?你有没有运行UPDATE STATISTICS?没有运行的问题比过去的版本(例如12.10)要多得多,但仍然值得检查。你在哪个平台上运行?事件表中的一行有多大? –
它仍然需要阅读所有索引页面才能计算每个COUNTRY的事件数量。 –
我的Informix版本是在Linux(Ubuntu)中运行的11.70.UC4D。我更新了统计数据,但没有任何区别。然而(正如我在下面告诉洛伦佐)删除索引(并强制连续扫描),查询执行得更快,这让我感到惊讶。我会尝试计算行大小。作为第一个近似值,它可能是每行大约1kB。 –