Chinaunix首页 | 论坛 | 博客
  • 博客访问: 104917472
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917473
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917474
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917475
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917476
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917477
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917478
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917469
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917480
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917481
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917482
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917483
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917484
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917485
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917486
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917487
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917488
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917489
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917490
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917491
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917492
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917493
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917484
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917495
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917496
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917497
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917498
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917499
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917500
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917501
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917502
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917503
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917504
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917505
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917506
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917507
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917508
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917499
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917510
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917511
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917512
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917513
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917514
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917515
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917516
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917517
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917518
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917519
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917520
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917521
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917522
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks

DB2 9 数据库管理(731考试)认证指南,第 3 部分: 数据访问(3)-sdccf-ChinaUnix博客
  • 博客访问: 104917523
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-04-13 14:16:17

developerWorks



创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42147) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42146) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42145) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42144) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42143) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42142) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42141) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42140) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42139) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42138) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42137) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42136) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42135) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42134) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42133) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42132) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42131) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42130) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42129) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42128) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42127) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42126) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42125) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42124) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42123) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42122) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42121) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42120) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42119) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42118) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42117) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42116) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42115) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42114) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42113) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42112) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42111) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42110) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42109) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42108) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42107) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42106) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42105) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42104) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42103) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42102) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42101) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42100) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42099) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42098) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42097) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~


创建和管理索引

对于任何刚刚创建好的数据库来说,索引都是一个重要的组件。尽管关系模型不需要使用索引来运行查询或计算结果,但若您在某些使用频率较高的表上创建索引,您的最终用户必然会更愉快!

索引是与单个表相关联的物理对象。任何永久表或声明好的临时表上都可以定义有多个索引。不能在视图上定义索引。

使用索引的主要原因有两条:

  • 确保数据值的惟一性
  • 提高 SQL 查询的性能

使用索引时,能够按一种排列好的顺序更迅速地访问数据,从而避免了使用临时存储排序数据这一耗时的任务。还可在计算列上创建索引,这样优化器就能够使用索引,而不是完成计算,从而节约了计算时间。在插入、更新和删除数据时,DB2 自动维护索引。







作为一名 DBA,您必须注意索引是怎样创建的。尽管对于任何数据库来说,索引都是可选的组件(但很重要),有的时候会为您自动创建索引。如果您没有预先规划索引,很可能就不会有足够的资源来创建或维护它们。

要创建索引,可以使用 CREATE INDEX 命令。但若您创建了一个表,且表中的一列具有 UNIQUE 属性;或者为表设置了参照约束(referential constraint);或者定义表时使用了维度(多维)属性,索引也会自动生成。所有这些条件都强制要求索引在表中具有惟一性,并且能够提供可以接受的性能。想像一下,如果数据库必须在每次需要检查一个值是否惟一时扫描整个表,情况有多糟糕!

除了生成索引的 SQL 命令之外,DB2 Control Center 中还有许多向导,可以帮助您决定在给定环境下,哪些索引是最恰当的。







在生成索引时,您会问的第一个问题就是:“哪个索引会给我带来最好的性能?” 是否应在表中的每一列上创建一个索引来确保性能最佳?或者应该仅创建一个使用户可直接访问数据的索引?

索引要占用您系统中的空间。它们可能位于与您正在为其编制索引的表相同的表空间中,也有可能位于独立的索引表空间中。由于表空间大小存在物理限制,您可能没有足够的空间来创建需要的全部索引。

更新索引需要花费时间。只要您插入、更新或删除记录,DB2 就必须对您的操作影响到的所有相应索引做出修改。因而,如果在您选中的表上创建 15 个索引,每次您更改数据时,将导致 15 次索引更新。在这种情况下,索引不但没有提供更好的性能,反而会导致更长的 响应时间。

最后,对于具有较少值(低基数)的列来说,索引可能并不合适。其他替代性的索引编制方法(多维集群或 MDC)可能更适用。







在您决定创建一些索引之前,应快速回顾一下表空间的概念。

表和索引放置在表空间 中。表空间用作数据库和存储实际表数据的容器对象之间的层。

容器 就是一个物理存储设备。可通过目录名称、设备名称或文件名称来标识。容器被指派给一个表空间,而一个表空间可以跨多个容器。如果以回避操作系统限制的方式将多个容器指派给一个表空间,可能会对一个容器可以具有的数据量造成约束。所有这些对象之间的关系如下图所示。

DB2 存储模型

尽管表是表空间中放置的基本对象,但您必须注意 DB2 系统内的其他对象,以及它们映射到表空间的方式。







那么在您真正想要创建的是索引时,为什么要对 CREATE TABLE 命令感兴趣呢?放置索引的困难在于它依赖于表的定义方式。

若在创建表时未提及位置,则该表将随为其创建的索引一同放置在默认表空间中。这也就意味着 USERSPACE1 表空间将很快被您的表和索引填满,这是因为它们都存储在相同的空间中。

即便您谨慎地将您的表放置在单独的表空间中,仍然可能会遇到问题,因为索引仍然会在相同的位置创建。您需要为索引指定位置!







创建表时,您可使用一个选项来指定一个或多个表空间,以便将表和索引放置在其中:

CREATE TABLE TEST (
  column 1 definition, column 2 definition, ...
) IN  INDEX IN 

这条命令给予您一个选项,可通过它来指定在什么位置创建表和索引。如果您未指定单独的表空间,索引将会在与表相同的表空间中创建。在表创建好之后,您就不能再选择在不同的表空间中创建索引。总而言之,要在创建索引之前进行规划!

如果您打算对表进行分区(范围分区),那么灵活性会进一步增加,您可将该表的每一个索引放置在自己的表空间中。该选项仅可用于分区表。







既然已经了解了将在哪里创建索引,现在应该来看一下 CREATE INDEX 命令了。该命令的基本语法如下:

CREATE  INDEX  ON 
  (
  column 1  ,
  column 2  ...
  )

UNIQUE 属性告诉 DB2,对于插入的所有值来说,索引必须是惟一的。若在 UPDATEINSERT 命令执行过程中发现重复值,将向应用程序返回一个错误。

括号中列出的列用于生成索引。可选的 ASC(升序)和 DESC(降序)关键字告诉 DB2 如何排列索引本身的值。在您发出一条排序结果的 SQL 语句时,该选项非常有用,如下所示:

SELECT * FROM EMPLOYEE
ORDER BY EMPNO DESC

若索引已按降序的顺序创建,DB2 可使用索引以有序序列的形式返回值,而不必单独执行一个排序步骤。如果结果集较大,这将节省可观的时间。若结果集同时采用升序和降序两种排序方法,那么在 CREATE INDEX 命令末尾处增加一个额外的 ALLOW REVERSE SCANS 更加有利。这告诉 DB2 在索引中包含额外的指针,允许记录内有效地向前和向后链接。在 DB2 9 中,所创建的任何索引都默认使用 ALLOW REVERSE SCANS,但在之前的版本中,您需要包含此选项,以便允许对同一个索引进行升序和降序访问。







DB2 能够为您所创建的索引添加额外的列。如果用户出于性能方面的原因需要在索引记录中保存额外的列,则 CREATE INDEX 命令允许用户指定并非实际索引一部分的列。

CREATE UNIQUE INDEX IX ON EMPLOYEE (EMPNO) INCLUDE (LASTNAME,FIRSTNME)

要将列包含于索引中,索引必须是惟一的。在创建索引时,额外的列将添加到索引值中。索引不会使用这些值来排序或确定惟一性,但可利用这些值满足 SQL 查询。例如,如下 SELECT 语句不需读取实际数据行:

SELECT LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO < '000300'

在 Visual Explain 中查看此语句,确定使用索引获得结果集的方法。

Visual Explain

在很多情况下,将数据放置在索引中有助于提高性能。但务必注意,不要使用过多的列,如果您使用的列过多,索引的大小将逐步接近物理数据本身的大小。







集群索引是 DB2 尝试使用的一种索引,DB2 用它在与其他具有相似索引键值的记录相同的页面上插入记录。若该记录上已经没有可用空间,则尝试将记录存储在附近的页面上。

使用集群索引的优势就是按关键字查找特定值(或某个范围内的值)的 SELECT 语句能够快速找到结果集,而不必扫描整个表。相似的键值将被放置在相同的数据页上,因而仅需读取整个表的一部分。此外,通过使用集群索引,表重组的需求也会减少。

为了确保有足够的空间可供在现有页中插入新行,应在创建表的过程中使用 PCTFREE 关键字,留出一些空间供未来插入和更新之用。一旦表加载完成,即可减少 PCTFREE 值,以允许向现有页中增加更多记录。

要在表上创建集群索引,向 CREATE INDEX 命令末尾处附加 CLUSTER 关键字即可,如下所示:

CREATE INDEX DEPTS_IX ON EMPLOYEE(WORKDEPT) CLUSTER

也可在创建索引时使用 PCTFREE 关键字。在表创建时指定一个较高的 PCTFREE,随后再将其设置为较低的值,这样就可以允许在索引中插入记录,而不会导致索引页的拆分。对于存在大量插入和删除活动的事务密集型环境来说,这是非常有用的。但若您的数据库主要用于查询工作负载,尽可能地在索引页中存储更多的数据可能更有优势。在此类情况下,应将 PCTFREE 设置为 0。从数据库的角度来看,在加载索引时必须读取的页会少一些,但维护索引的成本更高,因为可能会出现索引页拆分。







那么您应该为一个表创建多少个索引呢?实际上,答案取决于您针对表运行的应用程序类型。

确定为表定义的索引的典型数量时,可应用如下通用规则。索引的数量基于您的数据库的主要用途:

  • 对于在线事务处理(OLTP)环境,创建一个或两个索引
  • 对于混合查询和 OLTP 环境,创建两到五个索引
  • 对于只读查询环境,创建五个以上的索引

确定创建哪些索引的另外一个选择就是使用 Control Center 中的 Design Advisor。Design Advisor 将询问您许多与工作负载和数据库设计相关的问题,然后确定最佳索引。

Design Advisor







索引是参照完整性的关键组件。如果没有索引,性能会很糟,完整性检查的成本将异常高昂。

参照完整性允许您定义表之间和表内的所需关系。数据库管理器维护这些关系,它们可表示为参照约束,并且要求其他某些表列中也存在给定属性的所有值或表列。示例见下图:

参照完整性

让我们来查看一些键和约束的定义,以上图为例。

惟一键(unique key)是一组列,其中没有任何值与其他列中的值重复。仅惟一键可定义为各表的主键。惟一键被外键引用时,也可称为父键(parent key)

主键(primary key)是惟一键的特例。各表仅可具有一个主键。在上图中,DEPTNO 和 EMPNO 是 DEPARTMENT 和 EMPLOYEE 表的主键。

外键(foreign key)是表中的一列或一组列,引用同一表中或其他表中的惟一键或主键。它用于与惟一键或主键建立关系,并强制实施表之间的参照完整性。EMPLOYEE 表中的 WORKDEPT 列是一个外键,因为它引用了 DEPARTMENT 表中的主键,即 DEPTNO 列。

父键(parent key)是参照约束的主键或惟一键。父表是包含与同一个表或其他表中至少一个外键相关的父键的表。一个表可以是任意数量的关系中的父表。在上图中,具有主键 DEPTNO 的 DEPARTMENT 表是 EMPLOYEE 表的父表,而 EMPLOYEE 表包含外键 WORKDEPT。

子表(dependent table)是包含一个或多个外键的表。子表本身也可以是父表。一个表可以是任意数量的关系中的子表。例如,EMPLOYEE 表包含外键 WORKDEPT,该表是具有主键的 DEPARTMENT 表的子表。

参照约束(referential constraint)是一种断言,表明指定外键的非空值仅在其也作为指定父表的惟一键值出现时有效。参照约束的目的在于保证数据库关系得到维护、数据项规则得到遵循。

强制实施参照约束对某些 SQL 操作有着特殊的意义,这些操作依赖于一个表是父表还是子表。数据库管理器基于参照完整性规则在系统间强制实施参照约束。规则如下:

  • INSERT
  • DELETE
  • UPDATE






要在两个表之间定义外键关系:

  1. 创建带有主键的父表
  2. 将数据载入父表
  3. 创建带有外键关系的子表
  4. 将数据载入子表

对于前一屏中提到的 EMPLOYEE 和 DEPARTMENT 示例,DEPARTMENT 表的定义如下:

CREATE TABLE DEPARTMENT
  (
  DEPTNO    INT         NOT NULL PRIMARY KEY,
  DEPTNAME  VARCHAR(20) NOT NULL,
  MGRNO     INT
  )

DEPARTMENT 表的定义不一定非要在 DEPTNO 行中指定 PRIMARY KEY,您可使用 CREATE UNIQUE INDEX 命令来替代。

将数据载入 DEPARTMENT 表后,即可创建 EMPLOYEE 表。请注意,您不必立即将数据载入 DEPARTMENT 表,但必须首先为其填充数据,之后才能向 EMPLOYEE 表中插入数据。EMPLOYEE 表可定义如下:

CREATE TABLE EMPLOYEE
  (
  EMPNO     INT         NOT NULL PRIMARY KEY,
  FIRSTNAME VARCHAR(20) NOT NULL,
  LASTNAME  VARCHAR(20) NOT NULL,
  WORKDEPT  INT         NOT NULL,
  PHONENO   CHAR(12)    NOT NULL,
  FOREIGN KEY(WORKDEPT) REFERENCES DEPARTMENT(DEPTNO)
  ON DELETE RESTRICT)
  )

FOREIGN KEY 子句定义 EMPLOYEE 表和 DEPARTMENT 表之间的关系。由于存在这样的关系,若员工的 WORKDEPT 在 DEPARTMENT 表中不存在,该员工就无法向 EMPLOYEE 表中插入数据。此外,更新员工的 WORKDEPT 时,也需要根据部门列表进行检查。附加的 ON DELETE RESTRICT 子句告诉 DB2 防止删除 DEPARTMENT 表中的部门记录,除非 EMPLOYEE 表中不存在对该部门的引用。换句话说,一个部门的员工必须全部转移到另一部分,之后 DB2 才允许删除该部门。其他选项用于删除部门时将 WORKDEPT 设置为空(ON DELETE SET NULL),或者删除与此记录相关联的记录(ON DELETE CASCADE)。

从索引的角度来看,两个表都应定义主键。这将消除两个表内的重复,而且还会提高选择的性能。同样,DEPARTMENT 表中的主键是必需的,只有这样才能与 EMPLOYEE 表建立外键关系。







要创建一个具有与之相关的参照约束(外键)的表,用户必须具有恰当的权限。

考虑之前的 EMPLOYEE 和 DEPARTMENT 表示例(参见 参照完整性和索引)。若 DEPARTMENT 表归设备部门所有和管理,EMPLOYEE 表则由人事部门管理,这两个部门需要彼此协作。若 EMPLOYEE 表具有针对 DEPARTMENT 表定义的外键约束,那么如果没有人事部门员工的帮助,设备部门的用户就无法删除任何部门记录!这是由于针对 DEPARTMENT 表设置的 ON DELETE RESTRICT 规则。也就是说,用户可在您不知情的情况下对您的表设置严格的约束。为防止出现这种情况,必须对人事部门(EMPLOYEE 表的所有者)显式指定设置参照约束的权限:

GRANT REFERENCES(DEPTNO) ON DEPARTMENT TO USER PERSONNEL







索引是数据库设计中的关键组件。索引可用于提高性能、集群化页上的记录并确保记录的惟一性。

索引设计与工作负载的类型、为存储保留的空间数量密切相关。也可为索引添加额外的字段来提高查询性能。还有多种工具可帮助您定义系统所需的索引。

参照完整性是子表与父表之间的一种约束检查形式。为确保父表中的惟一性,同时在插入和更新处理过程中提高键检查的性能,索引是必要的。必须为子表所有者授予特殊的权限,使其能够针对不归自己所有的表创建参照约束。

阅读(42096) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~