[英]How to create a slow SQL query?
I have a million row table in Oracle 11g Express
and want to run a slow SQL select query so I can test stopping agents in various ways and observe the results on the database server.我在
Oracle 11g Express
有一百万行表,想运行一个慢速 SQL 选择查询,以便我可以通过各种方式测试停止代理并观察数据库服务器上的结果。
However no matter what I do, like self joins against a non-indexed column, selecting random rows using dbms_random, where/order by statements using non-indexed columns, the results all finish within a few seconds.但是,无论我做什么,比如针对非索引列进行自联接,使用 dbms_random 选择随机行,使用非索引列的 where/order by 语句,结果都在几秒钟内完成。
Is there a query I can write that will make it take a few minutes?是否有我可以编写的查询需要几分钟的时间?
I'm not quite sure what you mean by "stopping agents" in this context.在这种情况下,我不太确定您所说的“停止代理”是什么意思。 The only "agent" I can think of in this context would be an Enterprise Manager agent but I doubt that's what you're talking about and I don't see why you'd need a long-running query for that.
在这种情况下,我能想到的唯一“代理”是企业管理器代理,但我怀疑这就是您所说的,我不明白为什么您需要长时间运行的查询。
The simplest way to force a query to run for a long time is to have it sleep for a bit using the dbms_lock.sleep
procedure.强制查询长时间运行的最简单方法是使用
dbms_lock.sleep
过程让它休眠一段时间。 Something like就像是
CREATE OR REPLACE FUNCTION make_me_slow( p_seconds in number )
RETURN number
IS
BEGIN
dbms_lock.sleep( p_seconds );
RETURN 1;
END;
which you can call in your query您可以在查询中调用
SELECT st.*, make_me_slow( 0.01 )
FROM some_table st
That will call make_me_slow
once for every row in some_table
.这将调用
make_me_slow
一次在每一行some_table
。 Each call to make_me_slow
will take at least 0.01 seconds.每次调用
make_me_slow
至少需要 0.01 秒。 If some_table
has, say, 10,000 rows, that would take at least 100 seconds.如果
some_table
有 10,000 行,那至少需要 100 秒。 If it has 100,000 rows, that would take 1,000 seconds (16.67 minutes).如果它有 100,000 行,那将需要 1,000 秒(16.67 分钟)。
If you don't care about the results of the query, you can use the dual
table to generate the rows so that you don't need a table with materialized rows.如果你不关心查询的结果,你可以使用
dual
表来生成行,这样你就不需要一个包含物化行的表。 Something like就像是
SELECT make_me_slow( 0.01 )
FROM dual
CONNECT BY level <= 20000
will generate 20,000 rows of data and take at least 200 seconds.将生成 20,000 行数据,至少需要 200 秒。
If you want a pure SQL query (which gives you less ability to control exactly how long it's going to run),如果您想要一个纯 SQL 查询(这使您无法准确控制它将运行多长时间),
select count(*)
from million_row_table a
cross join million_row_table b
will generate a 1 million x 1 million = 1 trillion row result set.将生成 100 万 x 100 万 = 1 万亿行结果集。 That's likely to run long enough to blow out whatever
TEMP
tablespace you have defined.这可能会运行足够长的时间来耗尽您定义的任何
TEMP
表空间。
BEGIN
DBMS_LOCK.sleep(14);
END;
/
select * from table_c;
From Oracle12c
you could use:从
Oracle12c
你可以使用:
WITH FUNCTION my_sleep(t NUMBER) RETURN NUMBER
AS
BEGIN
DBMS_LOCK.SLEEP(t);
RETURN t;
END;
SELECT my_sleep(2)
FROM dual;
-- 2 after two seconds
This approach is nice because:这种方法很好,因为:
In most situations, the developer will not have the permission to create a FUNCTION or will not have access to DBMS_LOCK and will need GRANT execute on Schema.在大多数情况下,开发人员没有创建 FUNCTION 的权限或没有访问 DBMS_LOCK 的权限,并且需要在 Schema 上执行 GRANT。 The not so subtle way is to change the query (temporarily) to lock a record by using "for update".
不太微妙的方法是使用“for update”更改查询(临时)以锁定记录。
select * from employee where empId = 1 for update;
Now you can run your code and query will wait for lock to be released.现在您可以运行您的代码,查询将等待锁定被释放。 You will have to manually unlock the record after the test is complete.
测试完成后,您必须手动解锁记录。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.