我最近编写了一个复杂的 SELECT 语句(基于许多非常非常复杂的视图),在我的桌面上从 Toad 运行时需要 1 小时 50 分钟才能执行,而使用 cx_Oracle 从 Python 脚本运行时只快几分钟库(每 50 行写入一次刷新到磁盘)。单个结果集的总大小约为 8000 行,总计 5MB。在执行过程中,我的工作站没有抖动,CPU 负载也相当低。
在服务器上运行完全相同的查询花费了惊人的 21 秒来生成逐字节相同的结果集。这也是由相同的 Python/cx_Oracle 脚本生成的。
将 5MB 结果集文件从服务器传输到我的工作站只用了 3 秒,所以我认为网络带宽不是直接问题。
SQL*Net 或其相关库之一会是罪魁祸首吗?跨网络调用查询时是否存在一些非线性内存管理问题?5MB 的结果集很大,但在当今时代并不庞大。是否有一些缓冲区大小配置设置会有所帮助?我正在使用香草 Oracle 客户端安装。
工作站是带有 Oracle 10g 客户端的 Windows XP Pro SP3(只有 1GB 的 RAM)和带有 cx_Oracle 5.0.2 的适用于 Oracle Xpert 9.7.2.5 和 Python 2.6.2 的 Toad。该服务器是 Red Hat 2.6.9-67.ELsmp,位于四核 Xeon 3.8GHz 8GB 服务器上,运行 Oracle 10.2.0.4、Python 2.3.4、cx_Oracle 4.4.1。
编辑:哎呀!该文件只有5 MB,而不是 GB。很抱歉。
已解决:在我提到的提取查询之前运行了一个填充脚本。重新运行该填充脚本后,无论客户端程序的位置如何,提取查询都需要 2 小时才能运行。在第一次长期运行之后,结果集一定已经被缓存在某个地方,直到我有条不紊地检查所有组合时我才注意到这种效果。
在 oracle 中跟踪执行,您可能会看到您的工作站获取小块数据并快速增加延迟。
解决方案可能是批量获取结果,如下所示:
解决 TOAD 中的 Oracle 争用;看看toadworld,搜索
(抱歉,无法添加超链接)
我不是特别了解 Oracle,但是以前使用其他数据库的网络协议的经验告诉我,他们完全忽略了延迟问题。换句话说,即使没有过多的数据要传输,如果您必须为每个值多次往返服务器,事情仍然会变得很缓慢。
如果你给你的网络增加一点延迟,你可以测试这个理论(我知道这在 Linux 中是可能的,我只能想象在 Windows 中有一些方法可以做到这一点)并查看它是否会显着影响整体运行时。
另一种选择是某些处理可能正在客户端完成,这可能会传输超过 5 GB 的中间数据以获得结果。不过,这可能会在您的桌面上显示为相当显着的负载量,因此可能性不大。
所有迹象似乎都指向网络瓶颈。在这两台计算机之间进行文件传输时,您可以获得什么样的吞吐量?您可以尝试从另一台计算机上运行相同的查询,但在网络拓扑中更近一点吗?
有效传输速率为 6.2Mbps——一点都不好。这是在黑暗中拍摄的,但是……您是否忽略了告诉我们您的工作站和服务器之间有一个电缆调制解调器?:)
也许您的工作站与 IP 电话以菊花链方式连接,而您实际上以 10Mbps 的速度连接?
对不起,如果我说的很明显,但你没有在你的问题中提到你的网络配置。
需要考虑两点:
您是否先在 Toad 中执行查询,然后在 python+cx_Oracle 中执行查询?第一次执行查询,Oracle需要解析查询,创建执行计划,执行计划:从磁盘读入内存(缓冲缓存),执行join等,...第二次,Oracle使用相同的执行计划(存储在 SGA 中),并从缓冲区缓存中读取,而不是从磁盘中读取。第二次执行相同查询的时间可能会少很多。
将 8000 行/5GB 的数据(每行 655Kbytes !!!)加载到 TOAD 中,以便在 GUI 中显示它们,可能需要很长时间。使用 python+cx_Oracle 你不会显示任何东西,所以你在这里节省了很多时间。
编辑:好的,所以 8000 行/5 Mb 的数据(每行 655 个字节)对于 TOAD 显示来说应该不是问题。
一条 SELECT 语句应该完整地传送到服务器进行解析和执行。由客户来管理如何返回这些结果。我敢打赌,问题在于您的客户如何获得结果。我使用 TOAD 已经有一段时间了,所以我不知道它是否在进行数据的批量提取,但正如@slovon 所指出的那样,这是一个可以大大提高速度的地方。
只是为了笑,看看从你的工作站到服务器的 traceroute 报告了什么,反之亦然。
编辑:要尝试的另一件事是在服务器上运行您的 python 脚本,但通过服务器上的侦听器通过 TNS 连接。这应该让您了解 TNS 软件对您的查询有什么影响,同时消除任何干预的网络问题。
此外,确保您的 DNS 是健康的(必须能够进行反向查找)并且您没有在服务器上使用 DHCP。主机名中的下划线也是禁止的。
从 TOAD 和本地获取会话等待时间的跟踪。然后比较等待事件和时间,加上执行计划。计划可能不同。