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了
如果不大于,那就不是减同一个数了。找到第二小的数,自己算吧!