简体   繁体   English

如何创建慢速 SQL 查询?

[英]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:这种方法很好,因为:

  • you don't need to use separate PL/SQL block (BEGIN ... END;)您不需要使用单独的 PL/SQL 块 (BEGIN ... END;)
  • it is fully contained query它是完全包含的查询
  • does not "pollute" your schema (no need for creation object privilege)不会“污染”您的架构(无需创建对象权限)
  • it could be used for Time-Based Blind SQL Injection testing.它可用于基于时间的盲 SQL 注入测试。 More info: www.owasp.org/index.php/Blind_SQL_Injection更多信息: www.owasp.org/index.php/Blind_SQL_Injection

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM