這篇文章主要講解了“PostgreSQL掃描方法是什么”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“PostgreSQL掃描方法是什么”吧!
成都創(chuàng)新互聯(lián)是一家專業(yè)提供讓胡路企業(yè)網(wǎng)站建設(shè),專注與成都做網(wǎng)站、網(wǎng)站制作、html5、小程序制作等業(yè)務(wù)。10年已為讓胡路眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。
關(guān)系型數(shù)據(jù)庫(kù)都需要產(chǎn)生一個(gè)最佳的執(zhí)行計(jì)劃從而在查詢時(shí)耗費(fèi)的時(shí)間和資源最少。通常情況下,所有的數(shù)據(jù)庫(kù)都會(huì)產(chǎn)生一個(gè)以樹形式的執(zhí)行計(jì)劃:計(jì)劃樹的葉子節(jié)點(diǎn)被稱為表掃描節(jié)點(diǎn)。查詢節(jié)點(diǎn)對(duì)應(yīng)于從基表獲取數(shù)據(jù)。
例如,這一個(gè)查詢:SELECT *FROM TAB1,TAB2 where TAB2.ID>1000。假設(shè)計(jì)劃樹如下:
上面的計(jì)劃樹:“TBL1上的順序掃描”和“TBL2上的索引掃描”分別對(duì)應(yīng)于表TBL1和TBL2上的表掃描方法。TBL1上的順序掃描:從對(duì)應(yīng)頁(yè)中順序獲取數(shù)據(jù);索引掃描:使用索引掃描訪問(wèn)表2。選擇一個(gè)正確的掃描方法作為計(jì)劃的一部分對(duì)于查詢性能非常重要。
深入理解PG的掃描方法之前,先介紹幾個(gè)重要的概念。

HEAP:存儲(chǔ)表整個(gè)行的存儲(chǔ)域。如上所示,整個(gè)域被分割為多個(gè)頁(yè),每個(gè)頁(yè)大小默認(rèn)是8K。每個(gè)頁(yè)中,item指針(例如上述頁(yè)中的1,2)指向頁(yè)內(nèi)的數(shù)據(jù)。
Index Storage:只存儲(chǔ)KEY值,即索引中包含的列值。也是分割成多個(gè)頁(yè),每個(gè)索引頁(yè)默認(rèn)8K。
Tuple Identifier(TID):TID為6個(gè)字節(jié),包含兩部分。前4個(gè)字節(jié)為頁(yè)號(hào),后2個(gè)字節(jié)為頁(yè)內(nèi)tuple索引。TID可以定位到特定記錄。
當(dāng)前版本,PG支持以下掃描方法:順序掃描、索引掃描、索引覆蓋掃描、bitmap掃描、TID掃描。依賴于表基數(shù)、選擇的表、磁盤IO、隨機(jī)IO、順序IO等,每種掃描方法都非常有用。我們先創(chuàng)建一個(gè)表并預(yù)制數(shù)據(jù),并解釋這些掃描方法。
postgres=# CREATE TABLE demotable (num numeric, id int); CREATE TABLE postgres=# CREATE INDEX demoidx ON demotable(num); CREATE INDEX postgres=# INSERT INTO demotable SELECT random() * 1000, generate_series(1, 1000000); INSERT 0 1000000 postgres=# analyze; ANALYZE
這個(gè)例子中,預(yù)制1億條記錄并執(zhí)行analyze更新統(tǒng)計(jì)信息。
順序掃描
顧名思義,表的順序掃描就是順序掃描對(duì)應(yīng)表所有頁(yè)的item指針。如果一個(gè)表有100頁(yè),每頁(yè)有1000條記錄,順序掃描就會(huì)獲取100*1000條記錄并檢查是否匹配隔離級(jí)別以及where條件。因此,即使只有1條記錄滿足條件,他也會(huì)掃描100K條記錄。針對(duì)上表的數(shù)據(jù),下面的查詢會(huì)進(jìn)行順序掃描,因?yàn)橛写蟛糠值臄?shù)據(jù)需要被selected。
postgres=# explain SELECT * FROM demotable WHERE num < 21000; QUERY PLAN -------------------------------------------------------------------- Seq Scan on demotable (cost=0.00..17989.00 rows=1000000 width=15) Filter: (num < '21000'::numeric) (2 rows)
注意,不計(jì)算和比較計(jì)劃耗費(fèi),幾乎不可能直到選用哪個(gè)掃描方法。但是為了使用順序掃描,至少需要滿足以下關(guān)鍵點(diǎn):謂詞部分沒(méi)有可用的索引鍵;或者SQL查詢獲取的行記錄占表的大部分。如果只有少數(shù)行數(shù)據(jù)被獲取,并且謂詞在一個(gè)或多個(gè)列上,那么久會(huì)嘗試使用或者不使用索引來(lái)評(píng)估性能。
索引掃描
和順序掃描不同,索引掃描不會(huì)順序獲取所有表記錄。相反,依賴于不同索引類型并和查詢中涉及的索引相對(duì)應(yīng)使用不同的數(shù)據(jù)結(jié)構(gòu)。然后索引掃描獲取的條目直接指向heap域中的數(shù)據(jù),然后根據(jù)隔離級(jí)別判斷可見(jiàn)性。因此索引掃描分兩步:
從索引數(shù)據(jù)結(jié)構(gòu)中獲取數(shù)據(jù),返回heap中數(shù)據(jù)對(duì)應(yīng)的TID;然后定位到對(duì)應(yīng)的heap頁(yè)直接訪問(wèn)數(shù)據(jù)。由于以下原因需要執(zhí)行額外的步驟:查詢可能請(qǐng)求可用索引更多的列;索引數(shù)據(jù)中不維護(hù)可見(jiàn)信息,為了判斷可見(jiàn)性,需要訪問(wèn)heap數(shù)據(jù)。
此時(shí)可能會(huì)迷惑,索引掃描如此高效,為什么有時(shí)不用呢?原因在于cost。這里的cost涉及IO的類型。索引掃描中,為了獲取heap中的對(duì)應(yīng)數(shù)據(jù),涉及隨機(jī)IO;而順序掃描涉及順序IO,只有隨機(jī)IO耗時(shí)的1/4。
因此只有當(dāng)順序IO的代價(jià)大于隨機(jī)IO時(shí),才會(huì)選擇索引掃描。
針對(duì)上表和數(shù)據(jù),執(zhí)行下面查詢時(shí)會(huì)使用索引掃描。隨機(jī)IO代價(jià)小,從而查詢標(biāo)記快。
postgres=# explain SELECT * FROM demotable WHERE num = 21000; QUERY PLAN -------------------------------------------------------------------------- Index Scan using demoidx on demotable (cost=0.42..8.44 rows=1 width=15) Index Cond: (num = '21000'::numeric) (2 rows)
Index Only Scan
僅索引掃描和索引掃描類似,區(qū)別在于第二步,僅僅涉及到掃描索引數(shù)據(jù)。有兩個(gè)條件:查詢獲取的數(shù)據(jù)只有key列,且該列是索引的一部分;所有獲取的數(shù)據(jù)都是可見(jiàn)的。如下所示:
postgres=# explain SELECT num FROM demotable WHERE num = 21000; QUERY PLAN ----------------------------------------------------------------------------- Index Only Scan using demoidx on demotable (cost=0.42..8.44 rows=1 Width=11) Index Cond: (num = '21000'::numeric) (2 rows)
Bitmap Scan
是索引掃描和順序掃描的混合體。為了解決索引掃描的缺點(diǎn)并充分利用其優(yōu)點(diǎn)。正如上面所說(shuō),對(duì)于索引數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù),需要找到heap頁(yè)中對(duì)應(yīng)的數(shù)據(jù)。因此需要獲取一次索引頁(yè),然后獲取heap頁(yè),從而造成大量隨機(jī)IO。Bitmap掃描方法平衡了不使用隨機(jī)IO的索引掃描優(yōu)點(diǎn)。
Bitmap index scan:首先獲取索引數(shù)據(jù)并為所有TID創(chuàng)建bitmap。為了理解方法,可以認(rèn)為bitmap包含所有頁(yè)的哈希(基于頁(yè)號(hào)),每個(gè)頁(yè)的entry包含頁(yè)內(nèi)所有偏移的數(shù)組。
Bitmap heap scan:從頁(yè)的bitmap中讀取值,然后針對(duì)頁(yè)和偏移掃描數(shù)據(jù)。最后檢查可見(jiàn)性和條件并返回tuple。
下面查詢使用bitmap掃描,因?yàn)樗x擇的記錄很多(比如too much for index scan)但不是大量(too little for sequential scan)。
postgres=# explain SELECT * FROM demotable WHERE num < 210; QUERY PLAN -------------------------------------------------------------------------- Bitmap Heap Scan on demotable (cost=5883.50..14035.53 rows=213042 width=15) Recheck Cond: (num < '210'::numeric) -> Bitmap Index Scan on demoidx (cost=0.00..5830.24 rows=213042 width=0) Index Cond: (num < '210'::numeric) (4 rows)
再看另一個(gè)查詢,選擇同樣多的記錄但是僅僅索引列。不需要heap頁(yè)因次沒(méi)有隨機(jī)IO,因此這個(gè)查詢選擇index only scan而不是bitmap scan。
postgres=# explain SELECT num FROM demotable WHERE num < 210; QUERY PLAN --------------------------------------------------------------------------- Index Only Scan using demoidx on demotable (cost=0.42..7784.87 rows=208254 width=11) Index Cond: (num < '210'::numeric) (2 rows)
TID Scan
TID掃描是PG中非常特殊的一種方式,和Oracle中的基于ROWID查詢類似:
postgres=# select ctid from demotable where id=21000; ctid ---------- (115,42) (1 row) postgres=# explain select * from demotable where ctid='(115,42)'; QUERY PLAN ---------------------------------------------------------- Tid Scan on demotable (cost=0.00..4.01 rows=1 width=15) TID Cond: (ctid = '(115,42)'::tid) (2 rows)
此外,PG社區(qū)還在討論其他的掃描方法:MySQL中的“Loose Index Scan”、Oracle中的“index skip scan”、DB2中的“jump scan”。這個(gè)掃描方法用在指定場(chǎng)景:選擇的B-tree索引的key列值都不同。避免遍歷所有相等的key值,而只遍歷第一個(gè)唯一值然后跳到下一個(gè)大值。這項(xiàng)工作PG正在開(kāi)發(fā),同樣被叫做“Index skip scan”,未來(lái)可以在release中看到這個(gè)特性。
感謝各位的閱讀,以上就是“PostgreSQL掃描方法是什么”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)PostgreSQL掃描方法是什么這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
標(biāo)題名稱:PostgreSQL掃描方法是什么
URL地址:http://www.chinadenli.net/article26/iiicjg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、網(wǎng)站建設(shè)、企業(yè)網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、微信小程序、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)