資料庫表(臨時表)

2021-08-30 09:22:21 字數 4581 閱讀 8095

oracle中的段(segment)是占用磁碟上儲存空間的乙個物件。儘管有多種型別,不過最常見的段型別如下:

q 聚簇(cluster):這種段型別能儲存表。有兩種型別的聚簇:b*樹聚簇和雜湊聚簇。聚簇通常用於儲存多個表上的相關資料,將其「預聯結」儲存到同乙個資料庫塊上;還可以用於儲存乙個表的相關資訊。「聚簇」這個詞是指這個段能把相關的資訊物理的聚在一起。

q 表(table):表段儲存乙個資料庫表的資料,這可能是最常用的段型別,通常與索引段聯合使用。

q 表 分割槽(table partition)或子分割槽(subpartition):這種段型別用於分割槽,與表段很相似。分割槽表由乙個或多個分割槽段(table partition segment)組成,組合分割槽表則由乙個或多

個表子分割槽段(table subpartition segment)組成。

q 索引(index):這種段型別可以儲存索引結構。

q 索引分割槽(index partition):類似與表分割槽,這種段型別包含乙個索引的某個片。分割槽索引由乙個或多個索引分割槽段(index partition segment)組成。

q lob分 區(lob partition)、lob子分割槽(lob subpartition)、lob索引(lobindex)和lob段(lobsegment):lobindex和lobsegment段儲存大物件(large object或lob)的結構。對包含lob的表分割槽時,lobsegment也會分割槽,lob分割槽段(lob partition segment)正是用於此。有意思的是,並沒有一種lobindex分割槽段(lobindex partition segment)型別——不論出於什麼原因,oracle將分割槽lobindex標記為乙個索引分割槽(有人很奇怪為什麼要另外給lobindex取乙個特 殊的名字!)。

q 巢狀表(nested table):這是為巢狀表指定的段型別,它是主/明細關係中一種特殊型別的「子」表,這種關係隨後將詳細討論。

q 回滾段(rollback)和type2 undo段:undo資料就儲存在這裡。回滾段是dba手動建立的段。type2 undo段由oracle自動建立和管理。

段空間管理

從oracle 9i開始,管理段空間有兩種方法:

q 手 動段空間管理(manual segment space management):由你設定freelists、freelist groups、pctused和其他引數來控制如何分配、使用和重用段中的空間。在這一章中我會把這種空間管理方法稱為mssm,但是要記住,這是乙個我 自造的縮寫,oracle文件中沒有這個縮寫。

q 自動段空間管理(automatic segment space management, assm):你只需控制與空間使用相關的乙個引數:pctfree。建立段時也可以接受其他引數,但是這些引數將被忽略。

高水位線

hwm很重要, 因為oracle在全面掃瞄段時會掃瞄hwm之下的所有塊, 即使其中不包含任何資料。這會影響全面掃瞄的效能,特別是當hwm之下的大多數塊都為空時。要檢視這種情況,只需建立乙個有1,000,000行的表(或者建立其他有大量行的表),然後對這個表執行乙個select count(*)。 下面再刪除(delete)這個表中的每一行,你會發現儘管select count(*)統計出0行,但是它與統計出1,000,000所花的時間一樣長(如果需要完成塊清除,時間可能還會更長:有關內容請參加9.5.5 節)。這是因為oracle在忙於讀取hwm之下的所有塊, 檢視其中是否包含資料。 如果對這個表使用truncate而不是刪除其中的每一行,你可以比較 一下結果有什麼不同。truncate會把表的hwm重置回「0」,還會截除表上的相關索引。由於以上原因,如果你打算刪除表中的所有行,就應該選擇使用 truncate

(如果可以使用的話)

臨時表(temporary table)用於儲存事務或會話期間的中間結果集。臨時表中儲存的資料只對當前會話可見,所有會話都看不到其他會話的資料;即使當前會話已經提交 (commit)了資料,別的會話也看不到它的資料。對於臨時表,不存在多使用者併發問題,因為乙個會話不會因為使用乙個臨時表而阻塞另乙個會話。即使我們 「鎖住」了臨時表,也不會妨礙其他會話使用它們自己的臨時表。

臨時錶比常規表生成的redo少得多。不過,由於臨時表必須為其中包含 的資料生成undo資訊, 所以也會生成一定的redo。 update和delete會生成最多的undo; insert和select生成的undo最 少。

臨 時表會從當前登入使用者的臨時表空間分配儲存空間,或者如果從乙個定義者許可權(definer right)過程訪問臨時表,就會使用該過程所有者的臨時表空間。全域性臨時表實際上是表本身的乙個模板。建立臨時表的動作不涉及儲存空間分配;不會為此分 配初始(initial)區段,這與常規表有所不同。對於臨時表,執行時當乙個會話第一次在臨時表中放入資料時,才會為該會話建立乙個臨時段。由於每個會 話會得到其自己的臨時段(而不是乙個現有段的乙個區段),每個使用者可能在不同的表空間為其臨時表分配空間。

oracle的 臨時表與其他關聯式資料庫中的臨時表類似,這樣區別只是:oracle的臨時表是「靜態」定義的。每個資料庫只建立一次臨時表,而不是為資料庫中的每個儲存過程都建立一次。在oracle中,臨時表一定存在,它們作為物件放在資料字典中,但是在會話向臨時表中放入資料之前,臨時表看上去總是空。由於臨時表是靜態定義的,所以你能建立引用臨時表的檢視,還可以建立儲存過程使用靜態sql來引用臨時表,等等。臨時表可以是基於會話的(臨時表中的資料可以跨提交存在,即提交之前仍然存在,但是斷開連線後再連線後再連線時資料就沒有了),也可以是基於事務的(提交之後資料就消失)。下面

這個例子顯示了這兩種不同的臨時表

create global temporary table temp_table_session

2 on commit preserve rows

3 as

4 select * from scott.emp where 1=0

這是建立會話臨時表

on commit delete rows子句使得這是乙個基於事務的臨時表

如果你曾在sql server和/或sybase中用過臨時表,現在所要考慮的主要問題是:不應該執行select x, y, z into #temp from some_table來動態建立和填充乙個臨時表,而應該:將所有全域性臨時表只建立一次,作為應用安裝的一部分,就像是建立永久表一樣。在你的過程中,只需執行insert into temp(x, y, z) select x, y, z from some_table。

歸根結底,這裡的目標是:不要在執行時在你的儲存過程中建立表。這不是oracle中使用臨時表的正確做法。ddl是一種代價昂貴的操作:你要全力避免在執行時執行這種操作。乙個應用的臨時表應該在應用安裝期間建立,絕對不要在執行時建立。

臨時表可以有永久表的許多屬性。它們可以有觸發器、檢查約束、索引等。但永久表的某些特性在臨時表中並不支援,這包括:

q 不能有引用完整性約束。臨時表不能作為外來鍵的目標,也不能在臨時表中定義外來鍵。

q 不能有nested table型別的列。 在oracle 9i及以前版本中, varray型別的列也不允許;

不過oracle 10g中去掉了這個限制。

q 不能是iot。

q 不能在任何型別的聚簇中。

q 不能分割槽。

q 不能通過analyze表命令生成統計資訊。

在 所有資料庫中,臨時表的缺點之一是優化器不能正常地得到臨時表的真實統計。使用基於代價的優化器(cost-based optimizer,cbo)時,有效的統計對於優化器的成敗至關重要。如果沒有統計資訊,優化器就只能對資料的分布、資料量以及索引的選擇性作出猜測。 如果這些猜測是錯的,為查詢生成的查詢計畫(大量使用臨時表)可能就不是最優的。在許多情況下,正確的解決方案是根本不使用臨時表,而是使用乙個 inline view(要看inline view的例子,可以檢視前面執行的select,它就有兩個內聯檢視)。採用這種方式,oracle可以訪問乙個表的所有相關統計資訊,而且得出乙個最 優計畫

我經常發現,人們之所以使用臨時表,是因為他們在其他資料庫中了解到乙個查詢中聯結太多的表是一件「不好的事情」。但在oracle開發中,必須把這個知識忘掉。不要想著你比優化器要聰明,來乙個查詢分解成3個或4個查詢,將其子結果儲存在臨時表中,然後再合併這些臨時表;正確的做法是應該編寫乙個查 詢,直接回答最初的問題。在乙個查詢中引用多個表是可以的;oracle中在這個方面不需要臨時表的幫助

臨時表小結

如 果應用中需要臨時儲存乙個行集由其他表處理(可能對應乙個會話,也可能對應乙個事務),臨時表就很有用。不要把臨時表作為乙個分解大查詢的方法,即拿到一 個大查詢,把它「分解」為幾個較小的結果集,然後再把這些結果集合並在一起(這看來是其他資料庫中最常見的臨時表用法)。實際上,你會發現,在幾乎所有的 情況下。oracle中如果將乙個查詢分解為較小的臨時表查詢,與原來的乙個查詢相比,只會執行得更慢。我就經常看到人們這樣做,如果有可能把對臨時表的 一系列insert重寫為乙個大查詢(select),所得到的單個查詢會比原來的多步過程快得多。

臨 時表會生成少量的redo,但是確實還是會生成redo,而且沒有辦法避免。這些redo是為回滾資料生成的,而且在最典型的情況下,可以忽略不計。如果 只是對臨時表執行insert和selete,生成的redo量幾乎注意不到。只有對臨時表執行大量delete和update時,才會看到生成大量的 redo。 如果精心設計,可以在臨時表上生成cbo使用的統計資訊;不過,可以使用dbms_stats包對臨時表上的統計給出更好的猜測,或者由優化器使用動態取樣在硬解析時動態收集。

資料庫臨時表

建立方法 方法一 createtable temptablename 或select 欄位1,欄位2,into temptablename from table 方法二 createtable tempdb mytemptable tidint 說明 1 臨時表其實是放在資料庫tempdb裡的乙個使...

資料庫建立臨時表

表名前使用乙個 號,臨時表是區域性的,使用兩個 號,臨時表是全域性的,在斷開連線後sql會自動刪除臨時表 create table a id int,name varchar 50 insert into a id,name values 1,123 select from a drop table...

HIVE 資料庫臨時表

hive從0.14.0開始提供建立臨時表的功能,表只對當前session有效,session退出後,表自動刪除。語法 create temporary table 注意點 1 如果建立的臨時表表名已存在,那麼當前session引用到該錶名時實際用的是臨時表,只有drop或rename臨時表名才能使用...