1. 程式人生 > >oracle & sqlserver 資料儲存結構對比

oracle & sqlserver 資料儲存結構對比

學習不是一蹴而就,而是在於日積月累 -- 獻給不再年輕的自己

參考文件:oracle 9i 10 g 程式設計藝術,MSDN

這裡只列出sqlserver  & oracle 最後兩級的資料儲存結構對比

首先,看一下sqlserver 的資料儲存結構:

       【SQL Server 中資料儲存的基本單位是頁。為資料庫中的資料檔案(.mdf 或 .ndf)分配的磁碟空間可以從邏輯上劃分成頁(從 0 到n連續編號)。磁碟 I/O 操作在頁級執行。也就是說,SQL Server 讀取或寫入所有資料頁。

        區是八個物理上連續的頁的集合,用來有效地管理頁。所有頁都儲存在區中】【摘選自msdn】


        也就是說在sqlserver 中 資料儲存的最小的單位是頁,我們table 中的每一行的資料都是儲存在頁中的,頁的大小是固定的8kb。

        在資料頁上,資料行緊接著標頭按順序放置。頁的末尾是行偏移表,對於頁中的每一行,每個行偏移表都包含一個條目。每個條目記錄對應行的第一個位元組與頁首的距離。行偏移表中的條目的順序與頁中行的順序相反

oracle 的資料儲存結構

        塊(block)是 Oracle 中最小的空間分配單位。資料行、索引條目或臨時排序結果就儲存在塊中。通常 Oracle 從磁碟讀寫的就是塊。Oracle 中塊的常見大小有 4 種:2 KB、4 KB、8 KB 或 16 KB(儘管在某些情況下 32 KB 也是允許的;但是作業系統可能對最大大小有限制)。

    對比分析:

     sqlserver 頁

               標頭(頁頭):頁碼,頁型別,頁的可用空間以及擁有該頁的物件的分配單元ID.

                                      頁型別,頁的可用空間都好理解(頁型別:是資料頁還是索引頁,或者是其他型別。可用空間,顧名思義,就是還有多少儲存空間)

                                       頁碼知道是什麼東東,但是作用不明

                                       擁有該頁的物件的分配單元ID:這個不理解

               頁尾偏移量:記錄每行資料在資料儲存區域的地址 (oracle 是存放在了塊頭中)

               資料儲存:儲存資料的

     oracle塊

               首部:塊型別相關資訊(表塊,索引塊),塊中發生的活動事務和過去事務的相關資訊,以及塊在磁碟中的地址

               表目錄:行對應的表相關的資訊

               行目錄:塊中行的描述資訊。指標陣列,指向塊中資料部分的資料行

     問題:oracle 怎樣知道塊是否有空閒的儲存空間呢?

               oracle 是使用表的空閒列表來管理空閒儲存空間的:每一張表都會維護一個或者多個空閒列表,列表中維護了當前範圍內可用資料塊的一個列表。如果一個數據塊達到了最大的儲存量,那麼就從空閒列表中移除,反之如果從一個數據塊中刪除了一些資料,使其滿足了規定的ptcused 引數的值,那麼這個塊將會重新進入到空閒列表中。

     猜想:往sqlserver 中tablea插入一條記錄時 sqlserver 需要遍歷一下tablea 使用的頁,看看有沒有空閒的可以存放此條資料的空間,如果有,則存放,否則,接著找

          oracle:直接從空閒列表中取一個塊然後把資料放進去

          效能誰高誰低呢?

      上面提到了oracle 中的一個引數ptcused,和其對應的還有一個引數ptcfree,這兩個引數是做什麼用的呢?這是oracle 和 sqlserver 關於儲存的另外一個區別:

      sqlserver:頁大小8kb,不加控制,如果資料允許,可以存滿。假如現在已經儲存了7.8kb,現在又有一條新資料 (大於1kb)或者我更新了此頁中的某一條資料,更新完後此頁的資料大小會大於8kb,此時sqlserver 會怎樣處理呢?SQL Server 將從最大長度的列開始動態將一個或多個可變長度列移動到 ROW_OVERFLOW_DATA 分配單元中的頁,也就是說不得不把一部分資料移動到另外的頁上去。那在我們查詢時就需要把這兩個也都load 到記憶體中。

      以下內容摘選自 msdn

   【 行不能跨頁(這個不是太明白是什麼意思),但是行的部分可以移出行所在的頁,因此行實際可能非常大。頁的單個行中的最大資料量和開銷是 8,060 位元組 (8 KB)。但是,這不包括用 Text/Image 頁型別儲存的資料。包含varcharnvarcharvarbinarysql_variant列的表不受此限制的約束。當表中的所有固定列和可變列的行的總大小超過限制的 8,060 位元組時,SQL Server 將從最大長度的列開始動態將一個或多個可變長度列移動到 ROW_OVERFLOW_DATA 分配單元中的頁。每當插入或更新操作將行的總大小增大到超過限制的 8,060 位元組時,將會執行此操作。將列移動到 ROW_OVERFLOW_DATA 分配單元中的頁後,將在 IN_ROW_DATA 分配單元中的原始頁上維護 24 位元組的指標。如果後續操作減小了行的大小,SQL Server 會動態將列移回到原始資料頁】

     orale 是怎麼做的呢?

     主導思想是:我先給你預留點空間,萬一你要是update,你就可以用我預留的空間了,如果空間夠,就不用把資料放到別的塊上去了。

     怎樣實現的呢?在建立表時有兩個引數:ptcused,ptcfree。

            ptcfree 引數描述了為了以後新增資料預留空間佔資料塊中的百分比,比如這個數字是20,那麼對這個塊插入資料時如果資料總量佔到了這個塊的80%,就不允許再往這個塊中插入資料了。

           那麼是不是說我刪除了一部分資料,讓這個塊的空閒空間大於了20%,比如25%了,現在允許我插入一條小資料了吧?答案是不一定,需要看ptcused 的引數值。如果ptcused 的引數值是40,那麼對不起,只有空閒空間大於60%之後才允許插入資料。

     怎麼設定這兩個引數比較合適呢?下面給出了建議

          高 PCTFREE,低 PCTUSED:如果你插入了將要更新的大量資料,而且這些更新會頻繁地增加行的大小,此時就適合採用這種設定。這種設定在插入後會在塊上預留大量的空間(高PCTFREE),並使得將塊放回到 freelist 之前必須幾乎為空(低 PCTUSED)。
         低 PCTFREE,高 PCTUSED:如果你只想對錶完成 INSERT 或 DELETE,或者如果你確實要完成 UPDATE,但 UPDATE 只是縮小行的大小,此時這種設定就很適合