• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
编写人生
写写代码,写写人生
博客园    首页    新随笔    联系   管理    订阅  订阅
U9在SQL Server上的性能优化经验(转述) — 之 使用long型的特定构造主键

此文根据用友的文档《基于SQL Server 2008构建SOA大型管理软件技术实践》“翻译”而成,非原创。在baidu上看见此文,觉得写的很好,就将原先的PPT细化一下并除去废话。

 

第一篇讲的是主键的选择。

 我就不废话int32和guid主键的优缺点了,这是他的PPT说明。

 

用友采用的是long作为主键,这是原始PPT上的话:

 

为实现不同站点间能够互相交换数据,必须保证站点间主键不串号,所以在最前端用两位是站点编号,理论上是100个, 这个问题应该不大,但是我在想,两个站点如果是集团内部可以协商使用不同的编号,如果是两个集团之间呢?思考中,有点挑刺了。

不知道你注意到没有,他的年是三位,这样就可以节省一位,当然,我觉得可以再改进,将日期转化为数字更好,可以参考 datetime的Second实现:

public int Second
{
    
get
    {
        
return (int) ((this.InternalTicks / 0x989680L) % 60L);
    }
}

 

 这个是精确到秒的,可以想办法删除到日期。

为什么要在第二个部分放上日期呢?我猜想是希望数据被存储后,能够按照顺序存放,而不至于像GUID那样作为聚集索引后,数据插入时经常挪动位置(SQL Server新提供的创建GUID已经解决这个问题)。但是我觉得加入日期还是有问题的,这要看后面的顺序号。

最后一部分是顺序号,根据PPT说明,应该是采用存储过程获取序号,但是我在想,某个日期在申请一个序号后,必须记录已经用到哪个序号,而且是区分不同日期。(缓存也一样),这样就必须为每个日期建立独立的行保存序列号,如果整个数据库公用一个序列,我想一年也就365条记录无所谓,但是如果每个表独立序列,就是4000*365条记录(U9 大约4000张表),那对于性能要求高的序列运算,似乎不妥。

 

我的观点: 

我觉得U9的主键设计是很不错的设计。当然,我们可以站在巨人的肩膀上继续改进。 

我觉得他在规划段时,U9使用了十进制的概念,应该使用十六进制更好,有利于充分利用资源;

应删除日期的部分,而改成后面全部是序号,这样就只用为每个表维护一个序列计数器了。 

我的实践

在我参与设计的ERP中,为提高主键的性能,采用了以下措施:

1、使用int32的序列,一个表对应一个独立的序列,减少序列表的行数量。当然,没有考虑多站点的情况;

2、获取序列的API被设计成批量获取,例如:IEnumerable<int> GetSeq(int count),例如在保存某个单据时,你(Application)很清楚需要多少个新的序列值,这样可以批量而减少往返;

3、使用独立的应用程序服务处理序列,并采用类似买发票的原理来处理缓存、脱机应用,原理是:应用服务器获取一段(1000个)序列,并迅速保存结果到数据库,当客户端不断申请序列时,应用服务器并不需要写入数据而是直接在内存中扣减,如果出现断电,那么仅仅浪费一段编号而已。通过此方法解决了性能(使用缓存)、负载均衡(使用单一序列服务器)和脱机应用(联机时购买发票号)。此方案实际上是Oracle序列功能的改进版,因为SQL Server一直没有提供此功能搞的我很郁闷。

posted on 2010-09-22 13:59  编写人生  阅读(1247)  评论(1)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3