HSQLDB用户指南(第二章)1

779 篇文章 0 订阅
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

  [link]HSQLDB%d3%c3%bb%a7%d6%b8%c4%cf.pdf" />http://foas.blogchina.com/inc/HSQLDB%D3%C3%BB%A7%D6%B8%C4%CF.pdf[/link]

  第2章SQL问题

  本章由李博翻译,

  想征求一下大家的意见,有没有必要翻译这个文档。

  最新进展请看我的个人blog:http://foas.blogchina.com

  2.1本章目的

  在本章中就在HSQLDB主页论坛或邮件列表中多次出现的问题进行解答,如果你打算应用程序中使用HSQLDB的话,你最好阅读一下本章。

  2.2SQL标准支持

  1.7.3版本的HSQLDB支持SQL92、99和2003标准规定的SQL方言。这意味着HSQLDB中支持的标准特性(例如左外连接)的语法是有标准文本规定的。许多SQL92、99甚至更高级的特征在HSQLDB中得到了支持。对于SQL2003标准的大多数以及一些可选的特性进行支持。然而,对于某些标准的特性没有支持,所以HSQLDB就没有做出支持各个级别所有的标准特性的声明。

  “SQL语法”一章列出了HSQLDB所支持的所有的关键字和语法。当书写有关HDBSQL或者转换现有的有关HSQLDB的SQLDDL(数据定义语言)和DML(数据操作语言)语句的时候,你应该查阅一下HSQLDB所支持的语法,并对SQL语句作出相应的调整。

  SQL标准中保留的关键字是不能作为表明或字段名使用的。例如,“POSITION”被作为与Java中的String.indexOf()作用类似的函数加以保留。HSQLDB目前对使用它并不支持其用法或者能够区分清楚的关键字进行限制。例如,“ANY”和“BEGIN”是HSQLDB目前没有支持的两个关键字,所以你也可使用它们两个来作为表或者列的名称。不过你应该避免使用在HSQLDB将来版本中可能支持或者拒绝作为表定义或查询的保留字。全部SQL保留字列表请参看org.HSQLDB.Token的源代码。

  HSQLDB也支持一些SQL标准之外的关键字和表达式作为性能的增强。像asSELECTTOP5FROM..,SELECTLIMIT010FROM...或者DROPTABLEmytableIFEXISTS这样的表达式都是HSQLDB增强性能所支持。

  2.3约束和索引

  2.3.1主键约束

  在1.7.0版本之前,一个CONSTRAINT PRIMARYKEY(名为name的主键约束)被在内部翻译成一个唯一的索引,另外,一个隐藏列被添加到具有额外唯一索引的表上。从

  1.7.0开始,单一列主键和多列主键(single-columnandmulti-columnPRIMARYKEY)约束都得到支持。它们由主键列指定的唯一索引支持,而没有额外的隐藏列来维护它们的索引。

  2.3.2唯一性约束

  根据SQL标准,一个单一列上的唯一性约束表示不允许存在两个相同的值(空值出外),也就是说这样的列中可以一个或更多值为空(NULL)的行而不违反唯一性约束。

  多个列(c1,c2,c3,..)的唯一性约束表示这些列中的任何两个值的集合都不相等(除非至少其中有一个为空)。每一个单一列内部可以有重复的值。下面这里满足两列上的唯一性约束。

  例2.1.满足2列唯一性约束的列值

  1,2

  2,1

  2,2

  NULL,1

  NULL,1

  1,NULL

  NULL,NULL

  NULL,NULL

  自从1.7.2版本以来,对于空值的唯一性约束和索引的处理已经向遵循SQL标准过渡。唯一性约束列的值全为空的行通常都可以被添加到表中,所以对于唯一性约束的列来说,如果其中的一个行的值为空,那么多个行就可以具有相同这样的值。

  2.3.3唯一性索引

  在1.7.3中,用户定义唯一性索引仍然可以进行声明,但是它已经不被赞成使用了,你应该使用一个唯一性约束来替代唯一性索引。

  像在早期版本的HSQLDB中一样,名为 的唯一性约束通常在内部创建列的索引,所以它实际上和已经废除的唯一性索引声明具有相同的效果。

  2.3.4外键

  HSQLDB从1.7.0版开始具有单一列外键和多列外键。一个外键也可以被指定引用一个没有命名目标列的目标表。在这种情况下,目标表的主键列被用作引用列。任何外键中的一对引用和被引用的列应该具有相同的数据库类型。当声明了一个外键时,主键表被引用的列必须具有一个唯一性约束(或主键),而在引用列里会自动创建一个非唯一性索引。例如:

  CREATETABLEchild(c1INTEGER,c2VARCHAR,FOREIGNKEY(c1,c2)REFERENCESparent(p1,p2));

  parent表中的(p1,p2)列一定存在一个唯一性约束。child表中的(c1,c2)列会自动生成一个非唯一性索引。p1和c1列一定具有相同的类型(INTEGER),p2和c2列一定具有相同的类型(VARCHAR)。

  2.3.5索引和查询速度

  HSQLDB没有使用索引来改善查询结果的分类,但是索引在提高查询速度上起着至关重要的作用。如果一个没有使用索引的表中,进行类似于DELETE这样的查询操作的时候,表中所有的行记录都要被检查一遍。WHERE从句中的列有一个索引的话,那么查询操作就可能直接从第一个候选列开始,从而减少了要检查的列的数量。

  索引在多个表之间进行连接操作的时候显得更重要。在SELECT...FROMt1JOINt2ONt1.c1=t2.c2执行的时候,对t1中的行一个接一个的进行操作,来查找t2中没有与之匹配的行。如果没有t2.c2没有任何索引的话,那么,对于t1的每一行来说,要必须检查t2的所有行。然而有一个索引的话,在很短的时间内就能找到匹配的行。如果,查询(query)在t1上还有一个条件(例如,SELECT...FROMt1JOINt2ONt1.c1=t2.c2WHEREt1.c3=4),那么在t1.c3上创建一个索引的话,将会消除一个接一个的检查所有行的需要,并且将没返回一行的查询时间降低到1个毫秒以下。所以,如果t1和t2各有10000行记录,那么没有索引的查询将会检查100,000,000各行的结合。如果在t2.c2上创建一个索引的话,查询时间将会降低到只对10000行进行检查和对索引的查找。在t2.c2上有一个附加索引的话,只需要检查4行就可以得到第一个符合条件的结果行。

  对于主键和唯一列,将对自动生成索引,否则,你应该是用CREATEINDEX命令行来定义索引。

  注意:在HSQLDB中,多列(multiplecolumns)上的一个唯一性索引可以在内部用作列表第一列上的非唯一性列。例如,ONSTRAINTname1UNIQUE(c1,c2,c3);表示这是CREATEINDEXname2ONatable(c1)等价的表示方式,所以你只要列表第一列中一个的话,就不需要指定一个额外的索引。

  在1.7.3版本中,一个多列的索引将会加速包含所有列的连接和值的查询。你不需要在这些列上声明任何附加的单独的索引,除非你仅对这些列子集进行查询。例如,在三个列上拥有主键约束或唯一性约束或只一个普通的索引的表的行记录,在三个列的值都在WHERE从句中指定了时候,查询就会比较高效。例如,SELECT...FROMt1WHEREt1.c1=4ANDt1.c2=6ANDt1.c3=8将会使用t1(c1,c2,c3)上的索引(如果存在的话)。

  作为多键索引改进的结果,和以前想比,索引或约束声明列的顺序带给查询速度的影响大大减少。如果包含多较多不同值的列第一次出现,查询速度将会有一点提高。

  一个多列索引不会加快仅对第二列或第三列查询的速度。第一列必须在JOIN..ON或者WHERE条件中指出。

  查询速度很大程序上取决于JOIN..ON或者FROM从句中表的顺序。例如,下面的第二个查询在大的表中会更快一些(假如TB.COL3上有索引的话)。因为,如果下面的查询被用到第一表中(以及TB.COL3上有索引)的话,TB.COL3可以很快的估计出来:

  (TB是一个很大的表,但符合TB.COL3=4条件的仅仅只有几行记录)

  SELECT*FROMTAJOINTBONTA.COL1=TB.COL2ANDTB.COL3=4;

  SELECT*FROMTBJOINTAONTA.COL1=TB.COL2ANDTB.COL3=4;

  基本规则是将这样表放在首位:其中的一个列上具有一个缩小的条件(narrowingcondition)。1.7.3版本的HSQLDB具有为视图或用在查询中的子选择(subselect)创建自动的,快速的(on-the-fly)索引的特征。当一个索引被连接到一个表或一个视图的时候,会被添加到一个不同于所连接的视图里。

  2.3.6Where条件或者连接

  使用WhERE条件连接表可能会降低执行速度。例如下面的查询通常会比较慢,甚至有索引的时候:

  SELECT...FROMTA,TB,TCWHERETC.COL3=TA.COL1ANDTC.COL3=TB.COL2ANDTC.COL4=1

  下面的查询暗示TA.COL1=TB.COL2但是却没有显式地设置条件。如果TA和TB每个都含有100行的记录,那么即使在被连接的列上建有索引的是,也有10000个组合combinations)被连接到TC来满足这些列的条件。使用JOIN关键词,条件TA.COL1=TB.COL2将必须被显示声明,它将会使TA和TB行在被TC连接前降低它们的结合(combinations)次数,这样将会使对大表查询的执行大大加快:

  SELECT...FROMTAJOINTBONTA.COL1=TB.COL2JOINTCONTB.COL2=TC.COL3WHERETC.COL4=1

  如果连接种表的顺序改变了的话,那么下面查询的执行速度会被大大加快,所以使用了TC.COL1=1以及将列的行的较小集合连接在一起:

  SELECT...FROMTCJOINTBONTC.COL3=TB.COL2JOINTAONTC.COL3=TA.COL1WHERETC.COL4=1

  在上述的例子中,数据库引擎将TC.COL4=1自动应用到TC,仅仅连接了行的集合来使这个条件也满足其他的表。TC.COL4,TB.COL2和TA.COL1上的索引如果存在的话将会被使用,进而加速查询。

  2.3.7子查询和连接

  使用连接及建立最大性能的表顺序适用于所有的环节,例如,下面的第二个查询通常情况下比第一个更快,因为TA.COL1和TB.COL3有索引的缘故。

  例2.2.查询比较

  SELECT...FROMTAWHERETA.COL1=(SELECTMAX(TB.COL2)FROMTBWHERETB.COL3=4)

  SELECT...FROM(SELECTMAX(TB.COL2)C1FROMTBWHERETB.COL3=4)T2JOINTAONTA.COL1=T2.C1

  第二个查询将MAX(TB.COL2)转变成一个单行的表,但后将它连接到TA。因为TA.COL1上存在索引,所以这个查询的速度会非常快。第一个查询将会测试TA中的每一行记录,一次又一次地对MAX(TB.COL2)进行估算。

  [link=

<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值