oracle演算法
Ⅰ oracle的io次數是怎麼演算法
ORACLE 不會自動建立索引,之所以快是因為從內存中讀取比disk IO要快的原因。
LZ的概念理解有誤,我來舉例說明下。
ORACLE data一般緩存在SGA中的data cache中 1.表A有10000條數據,在0:00時刻對其進行查詢,則將表A的所有數據塊從disk緩存至data cache中。因此第二次查詢時直接從data cache中獲得速度變快。 2.0:05時刻 對表A進行更新等操作,20000行。再次對表A進行查詢,之前沒有變化的數據塊仍然直接從data cache中直接獲得。發生過變更,或新增的數據塊,需要重新從disk讀入data cache中,如果data cache空間已滿,就會將之前發生變更的臟數據塊及不常使用的數據塊清空出data cache,然後緩存新的數據塊。 因此整個過程中,不會出現你說的只能查到緩存數據的現象。分析你遇到的問題,很有可能是你用userA 進行查詢後發現表10000行,然後使用userB進行更新至20000行,但是userB並沒有commit。因此userA在查詢時仍然只能看到10000行。
Ⅱ oracle 四捨六入奇進偶舍的演算法
創建表
sql">createtabletest
(pricenumber(16,6));
insertintotestvalues(20.16666);
insertintotestvalues(32.2857);
insertintotestvalues(33.75);
insertintotestvalues(21.8);
insertintotestvalues(11.4);
insertintotestvalues(11.6);
insertintotestvalues(11.5);
insertintotestvalues(12.5);
insertintotestvalues(11.51);
insertintotestvalues(11.54321);
insertintotestvalues(11.50002);
執行
selectprice,
casewhensubstr(price,instr(price,'.')+1,1)=5andmod(substr(price,instr(price,'.')-1,1),2)=0thenfloor(price)
elseround(price)end
fromtest;
結果
Ⅲ 如何應對被公開的Oracle口令加密演算法
由於Oracle資料庫被廣泛應用,其口令加密演算法也是備受關注。最早在1993年comp.databases.oracle.server新聞組中有人披露了加密演算法的大部分細節。十年後,一本名為《Special Ops Host and Network Security for Microsoft, Unix and Oracle》的書中補全了演算法最重要的一個環節——DES演算法的KEY。至此,口令加密演算法已無秘密可言。接踵而來的是互聯網上出現多個了Oracle口令破解工具。Oracle在2007年推出的最新版本11g中,使用了新的更安全的加密演算法,但是新演算法的細節很快又在互聯網上被公開。為提供兼容,11g版本保留了11g以前版本使用的加密口令,利用這一漏洞仍然可以對11g版本的加密口令進行破解。
到底怎樣才能保證資料庫口令的安全呢?本文首先介紹Oracle資料庫各版本口令加密演算法的內容,然後針對演算法重點介紹加強資料庫安全性的應對措施。
口令加密演算法
從Oracle7到Oracle 10gR2,使用DES演算法對口令進行加密。對演算法進行分析,可以得出如下結論:口令不區分大小寫,任意大小寫組合均可登錄;由於只使用固定KEY,只要用戶名和口令相同,在任一DB中存放的加密口令都相同;由於採用了用戶名和口令串接的方式,所以用戶aaa、口令bbbccc的加密值與用戶aaabbb、口令ccc完全相同。
Oracle 11g版本的加密口令存放在SYS.USER$表中的SPARE4列中,而PASSWORD列中仍保留以前版本加密口令。由於客戶端計算加密口令需要用到SALT,在建立連接時,伺服器端將SALT明文傳送給客戶端程序。Oracle 11g中新的口令加密演算法中區分大小寫;由於加入了隨機數SALT,兩個不同用戶的口令即便完全相同,計算得到的SHA1的散列值也不同;不同DB中相同用戶相同口令,SHA1散列值也可能不同。
目前,大多數破解工具的工作方式是得到加密口令後,對每一個可能的口令進行加密計算,比較計算結果而確定是否正確。由此,抵禦口令破解可以從三個方面著手:防止加密口令外泄;在加密口令落入黑客手中後,口令也是不可破解的,或盡量增加破解的時間;即便是口令被破解,也是無用的,不能存取資料庫。
防止加密口令泄露
1.應用「最少許可權」原則,盡量限制可存取加密口令用戶的人數
在資料庫中檢查具有存取SYS.USER$或DBA_USERS許可權的用戶,並從不需要的用戶中收回許可權。但是操作並不簡單,這也是資料庫管理工作的特點。每一廠商的軟體中都實現了SQL標准之外的擴充,並且每一版本都有差異。限於篇幅,不可能對所有本文中建議的措施進行詳細的解釋說明,僅以此處檢查許可權為例展示DBA工作的復雜性。本文中如未說明,則默認版本為11g。應用於11g以前版本時,請讀者確認是否需要修改。
檢查許可權主要的工具是數據字典視圖(也可以直接存取SYS用戶的基表,但基表的定義沒有公布,官方不提供技術支持)。視圖DBA_TAB_PRIVS存放了資料庫中數據對象上的授權信息。假定用戶A1和A2可以存取SYS.USER$表,檢查在SYS用戶USER$上有存取許可權的用戶,可執行如下語句:
SELECT GRANTEE FROM DBA_TAB_PRIVS WHERE TABLE_NAME=『USER$』;
我們已經知道用戶A1和A2,都可以存取SYS.USER$表,但為什麼在上面查詢結果中沒有出現呢?這是因為在Oracle的許可權管理中,對一個表的存取許可權還可以通過系統許可權或角色賦予,而DBA_TAB_PRIVS中僅列出了直接的對象許可權的授予信息。對於SYS.USER$表而言,系統許可權SELECT ANY DICTIONARY和角色DBA都包含了這一表的存取許可權。所以完整列出所有可存取這一表的用戶應增加下面兩條查詢語句的結果:
SELECT GRANTEE FROM DBA_SYS_PRIVS WHERE PRIVILEGE=『SELECT ANY DICTIONARY』;
SELECT GRANTEE FROM DBA_ROLE_PRIVS WHERE GRANTED_ROLE=『DBA』;
通過上面的查詢語句,還是會遺漏某些用戶。如果把DBA角色授權給另一角色Admin,然後又將Admin角色授權給另一用戶NEWU,則此用戶可存取SYS.USER$表,但在上述三個查詢中並沒有直接列出NEWU的名字(角色Admin會出現在第三個查詢語句的結果中)。
顯然,Oracle的授權構成了一棵樹,完整的信息需要一段PL/SQL程序來完成。(對於11g以前版本,還需要檢查對DBA_USERS視圖有存取許可權的用戶和角色。SELECT_CATALOG_ROLE角色如被授權,則可以存取所有數據字典視圖,但不能存取SYS的基表。)
2.設定對加密口令存取的審計
如果當前系統中只有SYSDBA可以存取USER$,則一個變通辦法是審計SYSDBA的所有操作,其中也包括對USER$的存取。設置初始化參數audit_sys_operations =TRUE,重新啟動資料庫後激活對SYSDBA操作的審計。
審計文件的存放位置為:
11g版本中為:$ORACLE_BASE/admin/SID/ amp/ *.aud
11g以前版本為: $ORACLE_HOME/rdbms/audit/ *.aud。
嚴格限制和監視SYSDBA用戶活動的最好辦法是使用Oracle Database Vault組件。
3.在操作系統級限制對資料庫數據文件的存取
SYSDBA用戶的加密口令存放在$ORACLE_HOME/dbs下的口令文件orapw〈SID〉中。SYS.USER$表同樣需要在數據文件中存放,多數為SYSTEM表空間的第一個數據文件中。此外,EXPORT文件、REDOLOG文件以及TRACE文件中都可能出現加密口令。需要嚴格限制上述文件的存取許可權。
4.防止網路竊聽
在建立連接時,客戶端需要向伺服器端傳送用戶名和口令,並且伺服器端與客戶端需要相互發送這次會話使用的SESSION KEY。Oracle採用Diffie-Hellman KEY交換演算法和自己開發的O3LOGON協議完成上述任務。演算法的細節同樣已在互聯網上被公開。建立連接時上述信息如果被截獲,同樣可以被用來破解口令。更為嚴重的是,如果黑客事先已經獲得加密口令,結合SESSION KEY的信息,則不需要任何破解,執行簡單還原運算就可算出口令明文。
另外,設計SID時不要使用如ORCL、TEST、PROD等常用名字,設定PORT號為遠遠大於1521的數,都可以增加黑客SID掃描的難度和時間。
5. 刪除舊版的加密口令
存放在Oracle 11g資料庫中的以前版本的加密口令是口令破解工具的一個突破口。在沒有兼容性限制的系統中,可以考慮從系統中刪除舊版口令,從而增加破解難度。
具體操作如下:
在SQLNET.ORA中增加一行:SQLNET.ALLOWED_LOGON_VERSION=11(Oracle手冊中格式介紹有錯誤,不能加括弧:…=(11)),指定最低版本。
以SYSDBA登錄後,執行以下語句,刪除舊版口令。
update sys.user$ set password=NULL;
delete from user_history$;
commit;
設置修改後,基於OCI的工具如SQLPLUS、10gR1和10gR2版本都可以正常登錄,而JDBC type-4 則只有11g版本才允許登錄。
提高口令強度
1.禁止使用預設口令,禁止與用戶名同名的口令,禁止字典詞彙的口令
Oracle 11g中提供一個視圖DBA_USERS_WITH_DEFPWD,可以方便地查出系統中使用預設口令的所有用戶,不足的是還有不少遺漏。讀者可以在互聯網找到預設口令的列表,雖然是非官方的,但是比DBA_USERS_WITH_DEFPWD使用的官方的列表更全。破解工具附帶的詞彙表有的包括了大型英文詞典中全部詞彙,並支持詞彙與「123」之類的常用後綴進行組合。需要注意的是,有的詞彙表中已經出現了「zhongguo」這樣的字元串,所以漢語拼音組成的口令也是不安全的。檢查系統中是否存在弱口令的最常用方法就是使用前述口令破解工具進行攻擊。
2.規定口令最小字元集和口令最短長度
口令字元集最小應包括字母、數字和特殊符號,口令長度最短應不少於8位,對於安全性要求高的系統,最短長度應為12位以上。同樣,問題的關鍵在於DBA指定初始口令以及用戶修改口令時保證不違反上述這些規定。每一用戶都對應一個Profile,如在Profile中指定口令驗證函數,則每當創建或修改口令時,會自動檢查是否滿足驗證程序中所設定的條件,如果不滿足,則口令修改失敗。對口令明文進行檢查,顯然要比對加密口令破解效率高。此外,口令創建之時進行檢查可以及時封殺弱口令,不給黑客留下破解的窗口。
指定口令驗證函數的語句為:
ALTER PROFILE DEFAULT LIMIT PASSWORD_VERIFY_FUNCTION 口令驗證函數名;
上例中,為「DEFAULT」 Profile指定了驗證函數。對用戶進行分類後,應當為每一類用戶分別創建自己的Profile,而不是全部使用DEFAULT。關閉口令驗證函數的語句為:
ALTER PROFILE DEFAULT LIMIT PASSWORD_VERIFY_FUNCTION NULL;
在$ORACLE_HOME/rdbms/admin/下,腳本文件UTLPWDMG.SQL提供了示例的口令驗證函數,執行這一腳本,將創建一名為VERIFY_FUNCTION的函數( Oracle 11g中,增加新函數verify_function_11G )。這一函數可以對口令長度是否同時出現了字母數字元號進行檢查,檢查是否與用戶名同名,也檢查口令是否是幾個最常用的詞彙,如welcome、database1、account1等。最後,口令修改時檢查新舊口令是否過於相似。讀者實際使用時應該根據系統需要對這一函數進行必要的修改和擴充。
3.使用易記憶的隨機口令限定口令長度後,如果口令沒有規律很難記憶,則用戶會採用他們自己的方式記住口令,大大增加了遭受社會工程攻擊的可能性。DBA需要幫助用戶設計一個容易記憶而又不易破解的口令。一個簡單易行的方法是找用戶非常熟悉的一個句子,如One world One dream,然後將每一個空格替換為數字或符號:One3world2One1dream#。
定期更換口令
抵禦口令破解要從多方面著手
資料庫中存在多種許可權用戶,各種授權用戶構成一棵樹
應對口令泄露或被破解的措施是強制定期更換口令,設定口令重復使用限制,規定封鎖口令的錯誤次數上限及封鎖時間。即便是加密口令落入黑客手中,在被破解之前或入侵之前,修改了口令,則口令破解變得毫無意義。為了方便記憶,一般用戶有重新使用之前過期口令的傾向,如果對重用不加控制,則定期更換口令將失去意義。上述對口令的管理仍然是通過Profile完成:
ALTER PROFILE DEFAULT LIMIT
PASSWORD_LIFE_TIME 30
PASSWORD_GRACE_TIME 7
PASSWORD_REUSE_TIME 365
PASSWORD_REUSE_MAX 0
FAILED_LOGIN_ATTEMPTS 10
PASSWORD_LOCK_TIME UNLIMITED
PASSWORD_VERIFY_FUNCTION my_verify_function;
上面語句制定的口令管理政策為:口令的有效期為30天,隨後有7天的寬限期,寬限期後口令「過期」,必須更改口令後才能登錄。只有經過365天後才能重新使用以前的口令。在連續10次輸入口令錯誤後,賬號被封鎖,設定不自動解鎖,必須由DBA手動解除封鎖。口令驗證函數為my_verify_function。
Oracle 11g以前版本,預設設置中沒有設定口令的有效期,而在Oracle 11g中預設設置有效期為180天。程序中直接寫入口令的應用在升級到11g時一定要注意有效期問題,避免半年後應用突然無法自動運行。另外,口令的有效期對SYS用戶不起作用,DBA一定要主動定期更換口令。
另外一個措施是對登錄資料庫伺服器的主機進行限定,如指定網段或指定IP地址。進一步限定客戶端允許執行的程序,如對非本地登錄禁止使用SQLPLUS,只允許執行某特定應用。
認真實施本文中給出的措施後,可以很有效地防止口令被破解。然而我們的目的是提高資料庫系統的安全性,而不僅僅是保證口令不被破解。資料庫系統安全的任何一個環節出現問題,都會導致前功盡棄。黑客的目的是入侵系統盜竊數據,是不會按常理出牌的,會嘗試各種手段方式,如社會工程、安全漏洞、物理入侵等等,而不會執著地在口令破解上與我們較勁。這一點需要我們經常提醒自己,從而切實保證資料庫系統安全。
TechTarget中國原創內容
Ⅳ oracle 累計演算法
演算法:
declare
v_head varchar2(4000) :='(';
v_tail varchar2(4000) :=')';
v_body varchar2(4000) :=')';
v_head_section varchar2(4000) :='';
begin
for i in (select distinct username from test) loop
v_head_section := i.username || v_head;
v_body := '';
for j in (select username,subject from test) loop
if i.username = j.username then
v_body := v_body || ',' || j.subject;
end if;
end loop;
dbms_output.put_line(v_head_section || trim(',' from v_body) || v_tail);
end loop;
end;
Ⅳ oracle分頁演算法
先到程序里看看有沒有查詢到數據,如果有數據了再把數據放到 應答屬性里
保存在session中開銷大了點,建議你用一個方法來單獨分頁,可以用ajax獲取也可以用提交的方式來獲取,然後放到request里,應該可以取到
Ⅵ oracle 日期演算法
select * from sys.all_tab_columns where data_type like '%TIMESTAMP%' or data_type like '%DATE%'
你說的是不是這個意思啊
當然如果你要針對某張表,也可以後面加條件 table_name = '條名'
Ⅶ oracle 資料庫在存儲數據過程中,常用到一些演算法,包括一些架構,如何使得性能提升的模板有哪些
請參考《數據結構》
Ⅷ oracle什麼時候選擇hash join演算法
Hash Join只能用於相等連接,且只能在CBO優化器模式下。相對於nested loop join,hash join更適合處理大型結果集Hash Join的執行計劃第1個是hash表(build table),第2個探查表(probe table),一般不叫內外表,nested loop才有內外表Hash表也就是所謂的內表,探查表所謂的外表
兩者的執行計劃形如:
nested loop
outer table --驅動表
inner table
hash join
build table (inner table) --驅動表
probe table (outer table)
先看一張圖片,大致了解Hash Join的過程:
深入理解Oracle表:三大表連接方式詳解之Hash Join的定義,原理,演算法,成本,模式和點陣圖 - Andy - Andys home下面詳細了解一下Hash Join
一 Hash join概念
Hash join演算法的一個基本思想就是根據小的row sources(稱作build input 也就是前文提到的build table,我們記較小的表為S,較大的表為B)建立一個可以存在於hash area內存中的hash table然後用大的row sources(稱作probe input,也就是前文提到的probe table) 來探測前面所建的hash table如果hash area內存不夠大,hash table就無法完全存放在hash area內存中針對這種情況,Oracle在連接鍵利用一個hash函數將build input和probe input分割成多個不相連的分區分別記作Si和Bi,這個階段叫做分區階段;然後各自相應的分區,即Si和Bi再做Hash join,這個階段叫做join階段如果HASH表太大,無法一次構造在內存中,則分成若干個partition,寫入磁碟的temporary segment,則會多一個寫的代價,會降低效率至於小表的概念,對於 hash join 來說,能容納在 pga 中的 hash table 都可以叫小表,通常比如:
pga_aggregate_target big integer 1073741824hash area size 大體能使用到40多 M ,這樣的話通常可能容納 幾十萬的記錄hash area size預設是2*sort_area_size,我們可以直接修改SORT_AREA_SIZE 的大小,HASH_AREA_SIZE也會跟著改變的如果你的workarea_size_policy=auto,那麼我們只需設定pga_aggregate_target但請記住,這是一個session級別的參數,有時,我們更傾向於把hash_area_size的大小設成驅動表的1.6倍左右驅動表僅僅用於nested loop join 和 hash join,但Hash join不需要在驅動表上存在索引,而nested loop join則迫切需求一兩百萬記錄的表 join上 千萬記錄的表,hash join的通常表現非常好不過,多與少,大與小,很多時候很難量化,具體情況還得具體分析如果在分區後,針對某個分區所建的hash table還是太大的話,oracle就採用nested loop hash join所謂的nested-loops hash join就是對部分Si建立hash table,然後讀取所有的Bi與所建的hash table做連接然後再對剩餘的Si建立hash table,再將所有的Bi與所建的hash table做連接,直至所有的Si都連接完了二 Hash Join原理
考慮以下兩個數據集:
S={1,1,1,3,3,4,4,4,4,5,8,8,8,8,10}
B={0,0,1,1,1,1,2,2,2,2,2,2,3,8,9,9,9,10,10,11}
Hash Join的第一步就是判定小表(即build input)是否能完全存放在hash area內存中如果能完全存放在內存中,則在內存中建立hash table,這是最簡單的hash join如果不能全部存放在內存中,則build input必須分區。分區的個數叫做fan-outFan-out是由hash_area_size和cluster size來決定的。其中cluster size等於db_block_size * _hash_multiblock_io_counthash_multiblock_io_count是個隱藏參數,在9.0.1以後就不再使用了[sql]
sys@ORCL> ed
Wrote file afiedt.buf
1 select a.ksppinm name,b.ksppstvl value,a.ksppdesc description2 from x$ksppi a,x$ksppcv b
3 where a.indx = b.indx
4* and a.ksppinm like '%hash_multiblock_io_count%'
sys@ORCL> /
NAME VALUE DESCRIPTION
------------------------------ ----- ------------------------------------------------------------_hash_multiblock_io_count 0 number of blocks hash join will read/write at onceOracle採用內部一個hash函數作用於連接鍵上,將S和B分割成多個分區在這里我們假設這個hash函數為求余函數,即Mod(join_column_value,10)這樣產生十個分區,如下表:
深入理解Oracle表:三大表連接方式詳解之Hash Join的定義,原理,演算法,成本,模式和點陣圖 - Andy - Andys home經過這樣的分區之後,只需要相應的分區之間做join即可(也就是所謂的partition pairs)如果有一個分區為NULL的話,則相應的分區join即可忽略在將S表讀入內存分區時,oracle即記錄連接鍵的唯一值,構建成所謂的點陣圖向量它需要佔hash area內存的5%左右。在這里即為{1,3,4,5,8,10}
當對B表進行分區時,將每一個連接鍵上的值與點陣圖向量相比較,如果不在其中,則將其記錄丟棄在我們這個例子中,B表中以下數據將被丟棄{0,0,2,2,2,2,2,2,9,9,9,9,9}
這個過程就是點陣圖向量過濾
當S1,B1做完連接後,接著對Si,Bi進行連接
這里oracle將比較兩個分區,選取小的那個做build input,就是動態角色互換這個動態角色互換發生在除第一對分區以外的分區上面三 Hash Join演算法
第1步:判定小表是否能夠全部存放在hash area內存中,如果可以,則做內存hash join。如果不行,轉第二步第2步:決定fan-out數
(Number of Partitions) * C<= Favm *M
其中C為Cluster size,其值為DB_BLOCK_SIZE*HASH_MULTIBLOCK_IO_COUNTFavm為hash area內存可以使用的百分比,一般為0.8左右M為Hash_area_size的大小
第3步:讀取部分小表S,採用內部hash函數(這里稱為hash_fun_1)將連接鍵值映射至某個分區,同時採用hash_fun_2函數對連接鍵值產生另外一個hash值這個hash值用於創建hash table用,並且與連接鍵值存放在一起第4步:對build input建立點陣圖向量
第5步:如果內存中沒有空間了,則將分區寫至磁碟上第6步:讀取小表S的剩餘部分,重復第三步,直至小表S全部讀完第7步:將分區按大小排序,選取幾個分區建立hash table(這里選取分區的原則是使選取的數量最多)第8步:根據前面用hash_fun_2函數計算好的hash值,建立hash table第9步:讀取表B,採用點陣圖向量進行點陣圖向量過濾第10步:對通過過濾的數據採用hash_fun_1函數將數據映射到相應的分區中去,並計算hash_fun_2的hash值第11步:如果所落的分區在內存中,則將前面通過hash_fun_2函數計算所得的hash值與內存中已存在的hash table做連接將結果寫致磁碟上。如果所落的分區不在內存中,則將相應的值與表S相應的分區放在一起第12步:繼續讀取表B,重復第9步,直至表B讀取完畢第13步:讀取相應的(Si,Bi)做hash連接。在這里會發生動態角色互換第14步:如果分區過後,最小的分區也比內存大,則發生nested-loop hash join四 Hash Join的成本
⑴ In-Memory Hash Join
Cost(HJ)=Read(S)+ build hash table in memory(CPU)+Read(B) + Perform In memory Join(CPU)忽略cpu的時間,則:
Cost(HJ)=Read(S)+Read(B)
⑵ On-Disk Hash Join
根據上述的步驟描述,我們可以看出:
Cost(HJ)=Cost(HJ1)+Cost(HJ2)
其中Cost(HJ1)的成本就是掃描S,B表,並將無法放在內存上的部分寫回磁碟,對應前面第2步至第12步Cost(HJ2)即為做nested-loop hash join的成本,對應前面的第13步至第14步其中Cost(HJ1)近似等於Read(S)+Read(B)+Write((S-M)+(B-B*M/S))因為在做nested-loop hash join時,對每一chunk的build input,都需要讀取整個probe input,因此Cost(HJ2)近似等於Read((S-M)+n*(B-B*M/S)),其中n是nested-loop hash join需要循環的次數:n=(S/F)/M一般情況下,如果n大於10的話,hash join的性能將大大下降從n的計算公式可以看出,n與Fan-out成反比例,提高fan-out,可以降低n當hash_area_size是固定時,可以降低cluster size來提高fan-out從這里我們可以看出,提高hash_multiblock_io_count參數的值並不一定提高hash join的性能五 Hash Join的過程
一次完整的hash join如下:
1 計算小表的分區(bucket)數--Hash分桶
決定hash join的一個重要因素是小表的分區(bucket)數這個數字由hash_area_size、hash_multiblock_io_count和db_block_size參數共同決定Oracle會保留hash area的20%來存儲分區的頭信息、hash點陣圖信息和hash表因此,這個數字的計算公式是:
Bucket數=0.8*hash_area_size/(hash_multiblock_io_count*db_block_size)2 Hash計算
讀取小表數據(簡稱為R),並對每一條數據根據hash演算法進行計算Oracle採用兩種hash演算法進行計算,計算出能達到最快速度的hash值(第一hash值和第二hash值)而關於這些分區的全部hash值(第一hash值)就成為hash表3 存放數據到hash內存中
將經過hash演算法計算的數據,根據各個bucket的hash值(第一hash值)分別放入相應的bucket中第二hash值就存放在各條記錄中
4 創建hash點陣圖
與此同時,也創建了一個關於這兩個hash值映射關系的hash點陣圖5 超出內存大小部分被移到磁碟
如果hash area被占滿,那最大一個分區就會被寫到磁碟(臨時表空間)上去任何需要寫入到磁碟分區上的記錄都會導致磁碟分區被更新這樣的話,就會嚴重影響性能,因此一定要盡量避免這種情況2-5一直持續到整個表的數據讀取完畢
6 對分區排序
為了能充分利用內存,盡量存儲更多的分區,Oracle會按照各個分區的大小將他們在內存中排序7 讀取大表數據,進行hash匹配
接下來就開始讀取大表(簡稱S)中的數據
按順序每讀取一條記錄,計算它的hash值,並檢查是否與內存中的分區的hash值一致如果是,返回join數據
如果內存中的分區沒有符合的,就將S中的數據寫入到一個新的分區中,這個分區也採用與計算R一樣的演算法計算出hash值也就是說這些S中的數據產生的新的分區數應該和R的分區集的分區數一樣。這些新的分區被存儲在磁碟(臨時表空間)上8 完全大表全部數據的讀取
一直按照7進行,直到大表中的所有數據的讀取完畢9 處理沒有join的數據
這個時候就產生了一大堆join好的數據和從R和S中計算存儲在磁碟上的分區10 二次hash計算
從R和S的分區集中抽取出最小的一個分區,使用第二種hash函數計算出並在內存中創建hash表採用第二種hash函數的原因是為了使數據分布性更好11 二次hash匹配
在從另一個數據源(與hash在內存的那個分區所屬數據源不同的)中讀取分區數據,與內存中的新hash表進行匹配。返回join數據12 完成全部hash join
繼續按照9-11處理剩餘分區,直到全部處理完畢六 Hash Join的模式
Oracle中,Hash Join也有三種模式:optimal,one-pass,multi-pass⑴ optimal
當驅動結果集生成的hash表全部可以放入PGA的hash area時,稱為optimal,大致過程如下:
① 先根據驅動表,得到驅動結果集
② 在hash area生成hash bulket,並將若干bulket分成一組,成為一個partition,還會生成一個bitmap的列表,每個bulket在上面佔一位③ 對結果集的join鍵做hash運算,將數據分散到相應partition的bulket中當運算完成後,如果鍵值唯一性較高的話,bulket里的數據會比較均勻,也有可能有的桶裡面數據會是空的這樣bitmap上對應的標志位就是0,有數據的桶,標志位會是1④ 開始掃描第二張表,對jion鍵做hash運算,確定應該到某個partition的某個bulket去探測探測之前,會看這個bulket的bitmap是否會1,如果為0,表示沒數據,這行就直接丟棄掉⑤ 如果bitmap為1,則在桶內做精確匹配,判斷OK後,返回數據這個是最優的hash join,他的成本基本是兩張表的full table scan,在加微量的hash運算博客開篇的那幅圖描述的也就是這種情況
⑵ one-pass
如果進程的pga很小,或者驅動表結果集很大,超過了hash area的大小,會怎麼辦?
當然會用到臨時表空間,此時oracle的處理方式稍微復雜點需奧注意上面提到的有個partition的概念可以這么理解,數據是經過兩次hash運算的,先確定你的partition,再確定你的bulket假設hash area小於整個hash table,但至少大於一個partition的size,這個時候走的就是one-pass當我們生成好hash表後,狀況是部分partition留在內存中,其他的partition留在磁碟臨時表空間中當然也有可能某個partition一半在內存,一半在磁碟,剩下的步驟大致如下:
① 掃描第二張表,對join鍵做hash運算,確定好對應的partition和bulket② 查看bitmap,確定bulket是否有數據,沒有則直接丟棄③ 如果有數據,並且這個partition是在內存中的,就進入對應的桶去精確匹配,能匹配上,就返回這行數據,否則丟棄④ 如果partition是在磁碟上的,則將這行數據放入磁碟中暫存起來,保存的形式也是partition,bulket的方式⑤ 當第二張表被掃描完後,剩下的是驅動表和探測表生成的一大堆partition,保留在磁碟上⑥ 由於兩邊的數據都按照相同的hash演算法做了partition和bulket,現在只要成對的比較兩邊partition數據即可並且在比較的時候,oracle也做了優化處理,沒有嚴格的驅動與被驅動關系他會在partition對中選較小的一個作為驅動來進行,直到磁碟上所有的partition對都join完可以發現,相比optimal,他多出的成本是對於無法放入內存的partition,重新讀取了一次,所以稱為one-pass只要你的內存保證能裝下一個partition,oracle都會騰挪空間,每個磁碟partition做到one-pass⑶ multi-pass
這是最復雜,最糟糕的hash join
此時hash area小到連一個partition也容納不下,當掃描好驅動表後可能只有半個partition留在hash area中,另半個加其他的partition全在磁碟上剩下的步驟和one-pass比價類似,不同的是針對partition的處理由於驅動表只有半個partition在內存中,探測表對應的partition數據做探測時如果匹配不上,這行還不能直接丟棄,需要繼續保留到磁碟,和驅動表剩下的半個partition再做join這里舉例的是內存可以裝下半個partition,如果裝的更少的話,反復join的次數將更多當發生multi-pass時,partition物理讀的次數會顯著增加七 Hash Join的點陣圖
這個點陣圖包含了每個hash分區是否有有值的信息。它記錄了有數據的分區的hash值這個點陣圖的最大作用就是,如果probe input中的數據沒有與內存中的hash表匹配上先查看這個點陣圖,以決定是否將沒有匹配的數據寫入磁碟那些不可能匹配到的數據(即點陣圖上對應的分區沒有數據)就不再寫入磁碟八 小結
① 確認小表是驅動表
② 確認涉及到的表和連接鍵分析過了
③ 如果在連接鍵上數據不均勻的話,建議做柱狀圖④ 如果可以,調大hash_area_size的大小或pga_aggregate_target的值⑤ Hash Join適合於小表與大表連接、返回大型結果集的連接
Ⅸ oracle資料庫演算法問題
說給你個思路吧。
先找出最小值,然後乘以行數看是否大於3799.
如果大於就可以用3799除以行數,然後再減就ok了
如果不大於,那就不是減同一個數了。找到第二小的數,自己算吧!