我真的坚持这样做,因为数据库不是我的,不受我的控制。我可以构建一个类似的数据库在我的环境中进行测试,但是当然不应修改该数据库上的任何内容。现在,我可以做的就是尝试更改查询。
但是,即使像这样简单,还是第一次要花费 20 秒?
SELECT count(*) FROM SomeTableOf_500K_Rows
对于类似的SQL Server数据库(在架构和大小上具有相同的表),第一次只用1秒,下一次报告00:00:00
我的客户希望它更快,但实际上受到数据库/服务器的限制。
我对Oracle服务器的工作方式了解不多,测试数据库恰好位于同一本地网络中,这里不应该有任何涉及网络速度的原因。
我也尝试过这个,但是仍然是同样的问题:
SELECT /*+ NOCACHE */ count(*) FROM SomeTableOf_500K_Rows
我希望Oracle服务器在第一次执行这样的简单查询时以某种方式删除所有不必要的作业,以便它与SQL Server一样快(至少在执行时间附近)。
更新:
今天,我回到我的环境并进行了一些更多的测试,很奇怪,即使对于另一个只有74行的表,select count(*) from that_table
还是第一次仍然需要13-20秒?它比select * from that_table
慢得多,真的很奇怪。
更新跟踪信息:
通过使用tkprof
和一些语句来启用对当前会话的跟踪,我可以获得跟踪文件,并将其分析为输出文本文件(使用tkprof
)。真的结果告诉我没有什么新鲜的东西,只是一个表访问完全消耗黑框的 28秒 ,仅加载了 74 行(当然是第一次)。我的意思是黑匣子:
SQL ID: 9jpk7931105mh Plan Hash: 1282975746
select *
from
TestTable
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.01 0.01 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 2.92 28.96 7427 7436 0 74
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 2.93 28.97 7427 7436 0 74
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 92
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
74 74 74 TABLE ACCESS FULL TestTable (cr=7436 pr=7427 pw=0 time=2017 us starts=73 cost=2017 size=6734 card=74)
运行测试查询的总时间约为 29.651 秒,因为您可以看到上面的黑框几乎消耗了时间( 28.97 秒)。
如果可能的话,请在https://pastebin.com/Euv4mseu
处查看完整的输出文件(分析后)。还要注意,对于每个测试,我总是运行以下语句来清除缓存,以便查询不会受到缓存的影响:
alter system flush BUFFER_CACHE;
alter system flush shared_pool;
答案 0 :(得分:0)
我认为瓶颈是文件系统或高水位标记。
检查磁盘队列长度,它应该小于5,并且可能会有一些峰值。 Windows:使用“进程监视器”,然后单击“资源”以显示磁盘队列长度。 Linux:请参见Disk queue length
检查表的高水位线。 如果桌子过去更大,则会出现高水位线。 参见:Query HWM (High Water Mark)
替代检查 创建表的副本,然后尝试查询它。 该副本的水印不会很高。
创建表SomeTableOf_500K_Rows_Tst AS SELECT * FROM SomeTableOf_500K_Rows; SELECT count(*)FROM SomeTableOf_500K_Rows_Tst;
答案 1 :(得分:0)
您实际上需要确切的号码吗?有时,来自user_tables.num_rows的表统计信息足够好(如果它们是最近收集的)。对于大于等于12的Oracle版本,另一个选项可以是函数rox_count(基于超日志策略),该函数可以非常快速地返回几乎准确的结果。
要弄清楚查询为什么要花费这么多时间,您必须查看一个执行计划(如果可能,可以通过dbms_xplan.display_cursor从内存中获取):可能访问效率不高(可能是由于误导性统计数据)。或者计划中涉及的部分(表或索引)超出了应有的部分,可以进行重组/重建。
答案 2 :(得分:0)
是否总是需要20秒或仅在第一次运行?
以下只是一些基本检查。
如果您可以尝试SET AUTOTRACE ON
或使用SQL Developer进行解释,然后运行查询,您是否看到INDEX SCAN
或FULL TABLE SCAN
?
如果是FTS,请查看表中的索引:
SELECT * FROM ALL_TABLES WHERE TABLE_NAME = 'THE_TABLE';
如果没有索引,请尝试创建索引。
如果存在索引,它们中的任何一个都标记为无效吗?
如果所有命令均有效,请尝试查询,但添加提示以使用表上的索引之一(最好是主键(如果存在))。
如果即使使用索引(确认已在解释计划中使用该索引)也无法快速运行,并且该索引是现有索引(不是您刚创建的索引),请尝试
ANALYSE INDEX THE_INDEX VALIDATE STRUCTURE;
然后重试查询。
如果仍然没有更好的效果,请尝试使用核选项:
ALTER INDEX THE_INDEX REBUILD;
如果仍然没有更好的选择,那么您可能正需要深入研究Oracle巫术。
到那时,您将需要查看会话等待等。
答案 3 :(得分:0)
打开sqltrace并在跟踪文件上运行tkprof,看看您的等待事件是什么。
https://oracle-base.com/articles/misc/sql-trace-10046-trcsess-and-tkprof
答案 4 :(得分:0)
您可以检查表格上的并行选项是否已激活。如果是,请关闭
更改表YourTable noparallel;