Oracle数据库GUID作为主键执行速度过慢的原因到底在哪里呢?接下来我们开始介绍。首先介绍一下环境。数据库使用Oracle10g,所有字符类型的字段都是varchar2[1]。所有的主键都使用Guid,在数据库里是varchar2(36) 类型,相应的,实体的Id 属性的类型是string。ORM 使用的是NHibernate 2.1.0 和 FluentNHibernate1.1。
经过一番排查之后发现,问题的根源是NH将SQL语句传递给Oracle 时,所有字符型的参数都是nvarchar2 类型,而数据库里对应的字段却是varchar2 类型,这将导致Oracle 无法使用索引,终于造成全表扫描,所以数据量稍大就慢得不行。
***种解决方法是,把数据库中所有的字符型字段的类型由varchar2 更改为nvarchar2,出于种种原因我们不希望这么做。
第二种解决方法是,让NH 把varchar2 作为参数类型传递给Oracle。
事实上,NH 默认把.net 的string 映射为DbType.String[2],把DbType.String映射为nvarchar2[3]。把DbType.AnsiString 映射为varchar2[4]。
所以对于查询比较简单,只要把HQL的参数类型指定为AnsiString 就行了。
- var query = Session.CreateQuery(@"select t from Region as t
- where t.Id = :Id")
- .SetAnsiString("Id", id);
- var query = Session.CreateQuery(@"select t from Region as t
- where t.Id in (:Ids)")
- .SetParameterList("Ids", ids.ToList(), NHibernateUtil.AnsiString);
但是如何设置Update 和Delete语句的参数类型呢?这里有个小小的秘技,把映射文件里的属性类型指定为“AnsiString”即可。
- public class RegionMap : TreeNodeMap
- {
- public RegionMap()
- {
- Table("INFRA_REGION");
- Id(t => t.Id, "REGION_ID").CustomType("AnsiString");
- ...
- }
- }
注意:一定要使用CustomType()而不是CustomSqlType()。
当然了,要是把每一个配置文件都改一遍实在很烦,好像项目使用了Fluent NHibernate,只要添加一个 IdConvention 就行了。
- public class IdConvention : FluentNHibernate.Conventions.IIdConvention
- {
- public void Apply(FluentNHibernate.Conventions.Instances.IIdentityInstance instance)
- {
- instance.CustomType("AnsiString");
- }
- }
想要彻底一点的话,可以再加一个string类型的property的convention。
- public class StringPropertyConvention : IPropertyConvention, IPropertyConventionAcceptance
- {
- public void Accept(IAcceptanceCriteria
criteria) - criteria.Expect(x => x.Property.PropertyType == typeof(string));
- public void Apply(IPropertyInstance instance)
- {
- instance.CustomType("AnsiString");
- }
- }
把这两个Convention 加到配置里面:
- Session["SessionFactory"] = Fluently.Configure()
- .Database(OracleClientConfiguration.Oracle10
- .Dialect
() - .ConnectionString("User ID=iBlast;Password=不可说;Data Source=Moki")
- .QuerySubstitutions("true 1, false 0, yes 'Y', no 'N'")
- .UseOuterJoin()
- .ProxyFactoryFactory
() - .AdoNetBatchSize(1000)
- .Driver
()) - .Mappings(m => { m.HbmMappings.AddFromAssembly(Assembly.Load("Infrastructure.Repositories"));
- m.FluentMappings.AddFromAssembly(Assembly.Load("Infrastructure.Repositories"))
- .Conventions.Add
() - .Conventions.Add
() - .Conventions.Add
() - .Conventions.Add
() - .Conventions.Add
() - .ExportTo(@"F:\temp\"); })
- .BuildSessionFactory();
注意倒数第二行的.ExportTo(@"F:\temp\") 是为了测试一下生成的映射文件对不对而把映射文件输出到了 “F:\temp\”,映射文件应该像这个样子:
- ...
说明:
[1] 之所以使用varchar2 而不是 nvarchar2,除了考虑 varchar2 可以节省空间之外,主要是为了避免nvarchar2 排序时的性能问题。
[2] 见 NHibernate-2.1.0.GA-src\src\NHibernate\Type\TypeFactory.cs 第 197 行。
[3] 见 NHibernate-2.1.0.GA-src\src\NHibernate\Dialect\Oracle8iDialect.cs 第 92 行。
[4] 见 NHibernate-2.1.0.GA-src\src\NHibernate\Dialect\Oracle8iDialect.cs 第 88 行。
本文就介绍到这里,如果想了解更多Oracle数据库的知识,可以看一下这里的文章:http://database./oracle/。
【编辑推荐】
当前名称:Oracle数据库Guid作主键时执行速度超慢的原因在哪里
标题来源:http://www.shufengxianlan.com/qtweb/news19/457519.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联