在包含远程数据库的 Oracle 上测试 SQL 查询
Posted
技术标签:
【中文标题】在包含远程数据库的 Oracle 上测试 SQL 查询【英文标题】:Testing SQL query on Oracle which includes a remote database 【发布时间】:2009-05-27 14:54:23 【问题描述】:我们的开发数据库 (Oracle 9i) 使用远程数据库链接到远程共享数据库。
这个决定是几年前做出的,当时将一些数据库模式放在开发机器上并不实际——它们太大了。
我们在开发机器上有某些模式,我们通过使用 Oracle 的数据库链接以及开发机器上的一些同义词使远程模式看起来是本地的。
我遇到的问题是我想测试一段 SQL,它在数据库链接的任一侧连接模式中的表。
例如(简化案例):
select a.col, b.col
from a, b
where a.b_id = b.id
a 在本地数据库中
b 在删除数据库中
我在语言环境数据库中有一个同义词,因此“b”实际上指向 b@remotedb。
由于链接的原因,在开发环境中运行查询需要很长时间。查询在生产环境中运行良好(我认为基于 Oracle 成本的优化器不能很好地处理数据库链接)。
过去,我们一直不太擅长为这些类型的查询编写单元测试 - 可能是由于性能不佳 - 所以我想开始为它们创建一些测试。
有没有人为这样的查询编写单元测试的策略,以避免使用数据库链接的性能问题?
我通常会寻找尝试模拟远程服务的方法,但由于所有这些都在 SQL 查询中,我无论如何都看不到轻松模拟删除数据库。
【问题讨论】:
【参考方案1】:您应该从生产到开发中创建您需要的所有架构的精确副本,但不包含所有数据。您应该使用足够的数据填充架构,以便进行适当的测试。您还可以通过从生产服务器导出统计数据并将它们导入到您正在复制的模式的开发数据库中来操纵优化器,使其在测试系统上的行为类似于生产。这样,查询将使用您创建的数据集运行,但查询将使用与生产类似的计划进行优化。然后,您可以从理论上估计它将如何在生产中扩展。
【讨论】:
在本地创建模式并非易事。这是一个 Oracle 应用程序数据库(oracle.com/applications/home.html - 财务、人力资源、招聘等)。所有的模式和表都是高度耦合的。有数十种模式和数千个数据库对象。实际上,我只对这个数据库中大约 5 到 10 个表感兴趣。 不能从你感兴趣的数据库中导出5到10张没有数据的表,然后导入到dev db吗?如果您喜欢更完整的集合,您可以选择包含所有引用表,或者只包含您想要的包含/不包含数据的表。您可以提前在 dev db 中创建拥有该表的用户并为其分配适当的表空间和配额,然后导入导出文件以创建模式。然后用适当的数据填充它们,然后导入统计数据。【参考方案2】:将相关数据复制到您的开发数据库中并在本地创建表。
理想情况下,只需构建一个测试用例,它会告诉您:
-
SQL 正确(已解析)
使用几行测试数据即可正常运行
不要相信“让我们复制所有内容”,因为这意味着您将不知道自己正在测试什么(以及您缺少什么)。
如果有疑问,请创建一个表b
,其中只有一条记录。如果您在该区域遇到错误,请在了解可能出错的位置时添加更多行。
如果您想更进一步,请在单元测试中创建测试表(包含所有数据)。这样,您就可以记录您正在使用的测试数据。
[编辑] 你需要的是一个测试数据库。不要针对可以更改的数据库运行测试。理想情况下,测试应首先拆除整个数据库并从头开始重新创建(表、索引、数据、所有内容)。
在这个测试数据库中,只保留定义明确的测试数据,这些数据只会通过定义新测试(而不是由某人“只是做某事”)而改变。如果可以,请尝试针对内存数据库运行测试。
【讨论】:
谢谢。这意味着必须管理本地和远程数据库之间的同义词,即在运行测试时将同义词指向本地,然后在测试结束时将它们远程指向。我想这会奏效,但我希望有一种更透明的方式。 为什么还需要在开发数据库中拥有链接?只需放下它并始终在本地做事。或者创建第二个链接,以便您可以检查两个链接是否仍指向具有相同列的表。但永远不要通过链接运行测试。 我们需要这个链接,这样我们的应用程序才能在我们的开发环境中正常运行——远程数据库是一个 Oracle 应用程序套件,我们所有的核心用户数据都存储在其中。这是非常静态的,并且在开发人员之间共享。 查看我的编辑。不要针对 JUnit 测试数据库运行应用程序。 如果你有一个本地同义词和一个同名的表,Oracle 将使用这个表(首先在本地模式中搜索表,然后如果没有找到本地同义词,然后是公共同义词),所以理论上你可以临时创建本地表,应用程序应该继续工作,然后再次删除表,只留下同义词。这有点骇人听闻,但可能仅是数据库链接!【参考方案3】:我会建议物化视图。这些是在本地存储远程数据的视图。
【讨论】:
【参考方案4】:理论上,要进行单元测试,您可以使用根据您的测试用例创建和设计的任何受控数据集。它不必是您的实时或开发系统。这是假设您的设备足够便携。当您进行集成测试时,您可以使用当前的数据库/应用程序对其进行测试,无论如何这也可能在实时系统上(因此不需要数据库链接 - 我知道您的实时数据库在一个地方)。
我想说的是,您可以/应该在一组受控数据上测试您的单元(即您的组件、查询或您定义为一个单元的任何内容),这些数据将模拟不同的“用例”并且一次您完成测试并获得满意的结果,然后您可以继续进行集成 + 运行集成测试。
集成测试 - 您可以在实际环境中运行它,但前提是您通过单元测试证明您的组件是“防弹”的(如果您的公司的方法/理念没问题 :) - 系统管理员反应:“你疯了吗?!”)
如果您想回到过去并测试已经实现的单元,那何必费心呢?如果它们已经在生产中使用了一段时间而没有发生任何事件,那么我会争辩说它们没问题。但是,您的单元/查询总是有可能在侧面产生一些“缓慢滴答的定时炸弹”效应(随着时间的推移累积效应)。好吧,分析影响就是答案。
【讨论】:
这就是我们目前所做的。但是,受控数据集位于共享远程数据库中,因为从历史上看,该数据库太大而无法放入本地数据库中。这不仅仅是创建一两个表并用数据填充它们的问题。它是一个 Oracle 应用程序数据库,即一个复杂的第 3 方数据库。回顾旧查询的要点是,我们有一组自动回归测试,例如您可能会出于非功能性原因(例如性能)更改查询。很高兴知道您没有破坏它。以上是关于在包含远程数据库的 Oracle 上测试 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章