全掃瞄的影響因素之資料在資料塊中的儲存方式

2021-06-28 00:18:50 字數 3066 閱讀 7388

一方面,返回的資料行的百分比很小,也可能使用全掃瞄;另一方面,返回的資料行的百分比很大,也有可能不應該使用全掃瞄。

下面看乙個例子,看看即使返回的資料的百分比都很小,但資料的儲存方式的不同,優化器在選擇掃瞄的方式的不同。首先,建立了兩個同樣的具有10000行資料的表,然後,給出了每張表對於對乙個查詢的執行計畫。注意,在該例子中查詢只返回300行(只有總資料的3%)也會選擇全表掃瞄。

說明一下,我測試的時候返回100行的時候,優化器沒有選擇全掃瞄,而是使用了點陣圖索引掃瞄,我就加大返回的資料量來測試。

開始測試: 

表1的資料是用順序儲存,表2的是用隨機儲存。

1. 建表語句:

> 表1:

--測試資料的儲存方式(順序儲存)

create table seq_scan_store_1(

id serial,sid integer,

name1 character varying,

name2 character varying,

name3 character varying,

name4 character varying,

name5 character varying

);

--在sid上建立索引

create index seq_scan_store_1_sid_idx on seq_scan_store_1 using btree(sid );
> 表2:

--測試資料的儲存方式(隨機儲存)

create table seq_scan_store_2(

id serial,sid integer,

name1 character varying,

name2 character varying,

name3 character varying,

name4 character varying,

name5 character varying

);

--在sid上建立索引

create index seq_scan_store_2_sid_idx on seq_scan_store_2 using btree(sid );
2. 開始往兩張表插入資料:我是通過寫了兩個function插入資料。

> function1:

create or replace function func_seq_scan_1() returns void as $$

begin

for i in 1..10000 loop

insert into seq_scan_store_1(sid,name1,name2,name3,name4,name5) values(i/100,'zhansang'||(i/100),'lisi'||(i/100),'wangwu'||(i/100),'zhaoliu'||(i/100),'wangba'||(i/100));

end loop;

end$$language plpgsql;

> function2:

create or replace function func_seq_scan_2() returns void as $$

begin

for i in 1..10000 loop

insert into seq_scan_store_2(sid,name1,name2,name3,name4,name5) values(mod(i,100),'zhansang'||(i/100),'lisi'||(i/100),'wangwu'||(i/100),'zhaoliu'||(i/100),'wangba'||(i/100));

end loop;

end$$language plpgsql;

注意兩個function在插入sid欄位的不同。> 開始插入資料: 

select func_seq_scan_1();
select func_seq_scan_2();
當前資料在資料表裡的儲存方式如下圖所示:

表1: 順序儲存

表2: 隨機儲存

3. 檢視兩個表對應同乙個查詢的解釋計畫:

> 表1上:

原因是 sid<3的行在物理上僅儲存於資料檔案中的幾個資料塊中。

> 表2上:

原因是 sid<3的行在物理上僅儲存於資料檔案中的幾乎所有資料塊中。

4. 總結:

優化器沒有為這兩個相同的查詢選擇相同的解釋計畫,是因為這兩個表中的儲存方式是不同的,對錶1來說,只需要訪問幾個資料塊就能夠得到目標 資料,因此使用索引是很好的選擇;但是,對於表2來說,它的資料在物理上是零散儲存在表的所有資料塊中,對於它的查詢幾乎需要讀取所有的資料塊來獲取我們需要的300行資料,優化器計算出使用索引掃瞄讀取表中每乙個資料塊的時間可能比直接使用全表掃瞄讀取所有的資料塊,然後直接將每個塊中不需要的資料捨棄掉所花的時間還要長。

其實,使用索引,要先讀取索引塊,然後在讀取資料塊,如果是300行資料,就要先讀取至少300個索引塊,然後再讀取300個資料塊(後面會詳細介紹為什麼是至少300個索引塊),而全表掃瞄僅僅是讀取資料塊,優化器判斷後者所花的時間可能更少。

知道了資料是如何儲存以後,你就可能會理解為什麼優化器總是違背自己的意願不使用索引,而是使用索引掃瞄。

影響資料庫的因素

1.sql查詢速度 2.伺服器硬體 3.網絡卡流量 4.磁碟io 超高的qps和tps的風險 效率低下的sql 大量的併發風險 資料庫連線數被沾滿 max connections預設100,引數改的大一些 超高的cpu使用率 cpu資源耗盡而宕機 磁碟io 磁碟io效能突然下降 通過使用更快磁碟裝置...

oracle資料訪問途徑之全掃瞄

oracle資料訪問途徑之全掃瞄 oracle總共只有兩種基本的資料訪問途徑 全掃瞄或者索引掃瞄 統計資訊在優化器準備確定最優方法的過程中扮演了關鍵的角色。www.2cto.com 當對乙個物件進行全掃瞄時,與該物件相關的所有資料塊都必須取出並進行處理,以確定塊中所包含的資料行是否是你的查詢所需要的...

影響資料庫效能的因素

論壇上的資料庫愛好者們,對於資料庫底層的各種細節,內幕,等待事件,隱藏引數等津津樂道,對於調整好一條sql語句使之在查詢優化器 查詢引擎下能高效能運轉具有巨大的滿足感成功感,彷彿自己掌握了天下最有價值的真理,駕馭了天下最有難度的技術。但對於設計和開發出這個資料庫系統的人來說,他們看到此情此景,只好躲...