yzx99

导航

 

原来我的控件结构中,主键字都只能设一个,如:
  HYPara1.Table0_K = "DH"
  //HYPara1.PrimaryField = "DH"
  //HYPara1.SlaveryField = "DH"
这种做法最主要的问题在于:对于多关键字的表处理得不够理想,如,一个请假表,它的关键字是工号、日期与假别。我的控件无法直接处理,折衷的方案是,建立一个单号字段DH(不能用自动增加的ID字段,因为它不容易控制,即使表中有ID字段,但它的作用只在于标识记录的增加顺序,以及中间是否有删除的动作发生),然后把DH设为主关键字。insert、update、delete这三个都用DH进行,但事实中,我们要批量查询时,却用不到DH,比如要查某人在某段时间的请假情况,或是统计某人某段时间各种假别的请假情况。

但是随着自己技术的不断进步,为了提高数据库的响应速度,我们开始在表中使用多关键字。今天有时间就测试一下多关键字对性能到底提高多少?

我把实际的请假单数据拿来测试,总记录数:50709。建立如下表:
A01:关键字DH
A02:关键字DH,索引GH+RQ+JB
A03:关键字ID
A04:关键字ID,索引DH
A05:关键字ID,索引GH+RQ+JB
A06:关键字ID,索引DH,GH+RQ+JB
A07:关键字GH+RQ+JB
A08:关键字GH+RQ+JB,索引DH
(注意保存好建立以上表及插入记录、重整索引的SQL语句,以便全部删掉再来)

选择以下语句进行分析:
1. insert into A01(DH, GH, JB, RQ1) values('RS10320297', 10335, '0', '2009-01-01')
2. update A01 set GH=15141, JB='A', RQ1='2009-02-01' where DH='RS00320297'
3. delete from A01 where DH='RS10320297'
4. select * from A01 where DH='RS00320297'

5. select * from A01 where GH=10335
6. select * from A01 where GH=10335 and JB='A'

把分析结果列出一张表格
 1 2 3 4  5 6
A01 0.010 0.013 0.013 0.003  0.297 0.297
A02 0.010 0.013 0.013 0.003  0.004 0.003
A03 0.010 0.316 0.316 0.297  0.297 0.297
A04 0.010 0.013 0.013 0.003  0.297 0.297
A05 0.010 0.316 0.316 0.297  0.004 0.003
A06 0.010 0.013 0.013 0.003  0.004 0.003
A07 0.010 0.342 0.316 0.297  0.003 0.003
A08 0.010 0.035 0.013 0.003  0.003 0.003

假设以上的语句都是我们比较常用的,因此任何一个出现较长的时间都不行,把那些时间较长的方案排除,结果如下:
A02 0.010 0.013 0.013 0.003  0.004 0.003
A06 0.010 0.013 0.013 0.003  0.004 0.003
A08 0.010 0.035 0.013 0.003  0.003 0.003
结果与我预计的有一些差异,我原以为A08的方案会明显胜出(在语句5、6中体现),但事实上A08在语句5、6中的优势很弱,而之前我使用的A02方案不会差到哪里去。如果是这样,我其实没有加强我控件的必要。但再考虑:多数情况下是连接外表使用的(如员工档案表)、过滤条件多为GH、RQ、JB、排序方式多为GH、RQ、JB、几乎没有批量update语句。以及再打开查询分析器的运行时间及运行IO信息,可以看出在关联基础表时,A08的逻辑读远小于A02的逻辑读。毕竟A08是把GH、RQ、JB设为CLUSTERED的。所以总体感觉多关键字的技术还是有市场的。

但多关键字也有不好的地方:
·使用in或not in的语句不方便:
·参数传递时不一致:如单关键字时,我的存贮过程可以统一写成“S_A01 DH”,多关键字时,就要写成“S_A01 GH, RQ, JB”
·统一登记操作日志不方便:以前只要保存一个字段,现在还要组成一个字符串
·与明细表的关联不方便,明细表如果也用多关键字,好象冗余了点

权衡利弊,我们还是继续决定使用多关键字,但采用冗余设计,即也有多关键字,也有唯一的DH,并且DH设为索引,即A08所体现的,索引类型还可以设为UNIQUE-约束。DH继续用于增加/修改/删除/简单查询。

最后发现这下方案下,我要改的代码N少。有用到Table0_K的:HYF3Bar-->RecSave
C.R0.Properties("Resync Command") = "select * from " & C.Table0 & " " & _
                                    "where " & IIf(C.Table0_K = "", "ID", C.Table0_K) & "=?"
另外HYToolBar2-->RecSave用到,但我们不再继续改进HYToolBar2了
改为:
Dim sKey As String
sKey = C.Table0_K
If sKey = "" Then
  sKey = "ID=?"
ElseIf InStr(sKey, ",") > 0 Then
  sKey = Replace(sKey, " ", "") '取消空格
  If Right(sKey, 1) = "," Then
    sKey = Left(sKey, Len(sKey) - 1) '如果最后一个是逗号,取消
  sKey = Replace(sKey, ",", "=? and ") & "=?" '逗号替换成=? and,最后再加一个=?
Else
  sKey = sKey & "=?"
End If
C.R0.Properties("Resync Command") = "select * from " & C.Table0 & " " & _
                                      "where " & sKey

posted on 2009-02-08 20:05  yzx99  阅读(349)  评论(1编辑  收藏  举报