所以,我做了一些測試。
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。 –