正如在第1和第2部分中提到那样,有几个相对容易的改善性能的步骤你可以采取,这些步骤其中一个涉及到使用自动化工具“指导”你编写SQL语句,有许多生产性能分析或性能调整工具的厂家,在接下来的文章中,我们将对它们中的一个进行考察。
Quest Software
许多DBA和开发者使用一个名叫Toad的工具,它出自Quest Software公司,按照Quest Software网站上说法,Toad用户社区大约有500,000数量的用户,Toad的一个特色就是它有能力优化SQL查询,换句话说,Oralce 公司还没有占领调整顾问类型工具的市场。
关于顾问工具你有多种选择,理解它们是做什么的,如果你没有工作在生产或开发环境中你使用它们做什么?可能仅仅是喜欢,即使你处于一个开发环境,但你可能也没有使用到非常大的数据,本文的焦点集中在如何产生大量的数据,我们将介绍Quest Software的另一个产品:DataFactory for Oracle。
DataFactory
DataFactory的用途是为多种数据库平台快速创建有意义的测试数据,包括Oracle、DB2、Sybase以及ODBC兼容的数据库,正常情况下,每服务器零售价为595美元,在Quest Software的网站有一个可免费使用30天的版本可下载。
要获得这个软件(目前是5.5.0版本),你必须用真实的电子邮件地址注册,hotmail和gmail会被拒绝的,一旦你注册成功了,你将收到一封包含密钥的邮件,这个密钥用于解锁应用程序,开始30天的试用。
安装过程是相当简单的,如果你运行了微软的AntiSpyware,你可能会收到一个或多个错误,禁用掉实时保护后重新安装。
创建辅助对象
了解应用程序较好的方法是使用它的辅助对象,一般的过程有:
1、创建一个项目
2、在方案中创建表
3、运行脚本载入数据
不幸的是,在禁用了系统名参考的约束上获取刷新最好的方法是使用内置的辅助对象,使用一个反复的处理方法,可以禁用掉所有约束直到载入脚本运行不出现错误为止,然而,当Quest运行时修复了这个bug时,我可以标识和禁用这个约束。
启动DataFactory后,你可以选择启动自学教材,关于如何载入自学教材对象的指令(也就是所有的帮助)都在HTML文件中。
帮助系统中的指令规定了使用哪些表,但那是不准确的,下一步我会提到要用到哪些表(总共15个,都是以DF_前缀开头的)。
要创建辅助对象,安装下列步骤做:
1、选择工具(Tools)?创建辅助对象(Create Tutorial Objects),显示辅助对象创建向导。
2、从选择连接方法的下拉列表中选择合适的数据库类型。
3、点击下一步(Next)。
4、输入连接参数。
5、点击下一步(Next),显示完成页面。
6、点击完成(Finish),DataFactory辅助表就创建好了。
在创建表之前,你应该在数据库中先创建一个单独的方案对象,使用Oracle 10g,我创建了一个quest用户对象/方案(授予它connect和resource权限即可)。
点击Tools Create Tutorial Objects
辅助设置向导显示它自己的版本和oracle的logo
在完成页显示一列表名
DataFactory告诉你创建成功了
在左边框架中显示了项目文件夹
在主菜单上点击运行按钮(Run),立即报出ORA-02291错误,这是违反了完整性约束的错误提示(某些表上还不止一次),因为在一个外键关联的列上载入的数据没有同时往主表插入对应的数据,几乎所有的约束命名都采取SYS_Cxxxxxx命名结构,意味着它们不是明确的名字。
为了解决完整性约束问题,你可以禁用掉约束(只要你知道要修改哪个表),下面的查询和ALTER TABLE命令显示识别并禁用有问题的约束:
SQL> select owner, constraint_name, table_name, column_name 2 from all_cons_columns 3 where constraint_name like '%9814%'; OWNER CONSTRAINT_NAME TABLE_NAME COLUMN_NAME ----- ------------------------------ -------------------- ------------ QUEST SYS_C009814 DF_ORDERS CUSTID SQL> alter table df_orders 2 disable constraint sys_c009814; Table altered. |
结果(Results)窗口显示你的脚本完全成功执行了,意味着你可以看看究竟创建了些什么。
不是一次分析一个表,使用内置的DBMS_STATS(它是Oracle推荐的分析工具包),如果你使用的是Oracle 10g,你应该添加一个WHERE dropped='NO'条件阻止在显示查询结果时显示被删掉的表。
SQL> execute dbms_stats.gather_schema_stats('QUEST'); PL/SQL procedure successfully completed. SQL> select table_name, num_rows 2 from user_tables 3 where dropped='NO'; TABLE_NAME NUM_ROWS -------------------- ---------- DF_TITLES 100 DF_MOVIE_CUSTOMER 1100 DF_MOVIE_EMPLOYEE 900 DF_DUMMY 1100 DF_AUTHORS_TITLES 1100 DF_MOVIE_RENTAL 700 DF_PRODUCTS 100 DF_MOVIE_TAPE 400 DF_CUSTOMERS 1100 DF_AUTHORS 1100 DF_MOVIE_DISTRICT 1100 DF_ORDERS 101 DF_MOVIE_MOVIE 900 DF_ORDERDETAILS 200 DF_MOVIE_STORE 500 15 rows selected. |
返回项目或列表,在列表中选择一个表,将会显示它的列和列的数据类型,你可能需要在结果(Results)和子段(Children)之间使用固定按钮功能。
使用DF_MOVIE_CUSTOMER作为一个例子,如何查看它的数据?随机字符串选项刚好准确地用于这里。
辅助表上更多的内容
在外键列上有索引吗?
SQL> select index_name, table_name, column_name, column_position 2 from user_ind_columns; INDEX_NAME TABLE_NAME COLUMN_NAME COLUMN_POSITION ------------ -------------------- -------------------- --------------- SYS_C009823 DF_MOVIE_DISTRICT DISTRICTID 1 SYS_C009827 DF_MOVIE_STORE STOREID 1 SYS_C009830 DF_MOVIE_EMPLOYEE EMPID 1 SYS_C009837 DF_MOVIE_CUSTOMER CUSTID 1 SYS_C009841 DF_MOVIE_MOVIE MOVIEID 1 SYS_C009845 DF_MOVIE_TAPE TAPEID 1 SYS_C009850 DF_MOVIE_RENTAL TAPEID 1 SYS_C009850 DF_MOVIE_RENTAL CUSTID 2 SYS_C009850 DF_MOVIE_RENTAL RENTDATE 3 SYS_C009810 DF_CUSTOMERS CUSTID 1 SYS_C009813 DF_ORDERS ORDERID 1 SYS_C009816 DF_PRODUCTS PRODUCTID 1 SYS_C009819 DF_ORDERDETAILS ORDERID 1 SYS_C009819 DF_ORDERDETAILS PRODUCTID 2 14 rows selected. |
输出内容意味着什么?你可以立即判断出这样一个事实,不是所有表上都有主键,有15个表,但这里只返回了14行(或如果使用distinct的话,只返回11行),为什么我们会知道这个结果?因为创建主键时会自动创建一个索引,如果你在载入脚本中禁用了所有的引用完整性约束,你还会怀疑什么呢?
Oracle推荐将索引列作为经常访问的关联列,常见的规则是索引列用于where子句,缺少索引,你应该怀疑“create table”部分没有创建外键索引列。
下面的查询显示了带外键的表名/列名:
SQL> select a.constraint_name, b.constraint_type, 2 a.table_name, a.column_name 3 from user_cons_columns a, all_constraints b 4 where a.constraint_name=b.constraint_name 5 and constraint_type = 'R'; CONSTRAINT_NAME C TABLE_NAME COLUMN_NAME ---------------- - -------------------- ------------- SYS_C009831 R DF_MOVIE_EMPLOYEE SUPERVISORID SYS_C009828 R DF_MOVIE_STORE DISTRICTID SYS_C009821 R DF_ORDERDETAILS PRODUCTID SYS_C009820 R DF_ORDERDETAILS ORDERID DFMOVIESTOREFK2 R DF_MOVIE_STORE MANAGERID SYS_C009852 R DF_MOVIE_RENTAL TAPEID SYS_C009851 R DF_MOVIE_RENTAL CUSTID SYS_C009838 R DF_MOVIE_CUSTOMER STOREID SYS_C009814 R DF_ORDERS CUSTID SYS_C009846 R DF_MOVIE_TAPE MOVIEID DFMOVIEEMPFK2 R DF_MOVIE_EMPLOYEE STOREID 11 rows selected. |
这是最终结果吗?怀疑被证实了,外键没有被索引。
从管理和维护角度来看,为什么只有两个约束是明确命名的而剩下的都是系统命名的?实际上是这个方案总共有51个约束,这里只是发生了两个命名的约束。
小结
从这次探索来看,工具如DataFactory或你自己编写的脚本最关键的地方是能够产生百万计的测试样本数据,如果不能保证引用完整性,或在数据建模方面的最佳实践,它有什么好处?如果你打算在应用程序上调试查询,测试数据需要反应应用程序如何使用它。如果你依赖于数据完整性,你的测试数据需要支持并遵从父表/子表关联关系。
从设计的立场来看,有两个最佳实践容易被违背,其一是外键列无索引,其二是3个主要项目(主键、外键和索引)没有明确的名字。第三个可能是在表上无主键,难道在每个表上都需要主键吗?不是!但大多数情况下,每个表都需要主键,即使没有主键,你也要知道为什么没有设置主键,换句话说,不规范的表应该是有意识的决定,而不是失败。
本文作者:未知