我有一些运行很长时间(20-30分钟)的查询。如果同时启动大量查询,则会快速耗尽连接池。
是否可以将长时间运行的查询包装到一个语句(过程)中,该语句将一般查询的结果存储到临时表中,终止连接,然后根据需要fetchin(轮询)结果?
编辑:查询和数据结构已经过优化,“检查您的指数和执行计划”等提示对我不起作用。我正在寻找一种方法来存储通用结果集的[也许]字节表示,以便稍后进行检索。
答案 0 :(得分:6)
首先,20-30分钟是查询的极长时间 - 您确定没有遗漏查询的任何索引吗?请检查您的执行计划 - 您可以通过良好的索引获得巨大的性能提升。
在MySQL中,你可以做到
INSERT INTO `cached_result_table` (
SELECT your_query_here
)
(当然,cached_result_table
需要与SELECT
返回完全相同的列结构,否则会出错。)
然后,您可以查询这些缓存的结果(而不是原始表),并且只是不时运行上述查询 - 更新cached_result_table。
当然,查询最初需要至少运行一次,这需要你提到的20-30分钟。我建议在请求数据之前预先填充缓存表,并保留一些锁定机制以防止更新查询同时运行多次。伪代码:
init:
insert select your_big_query
work:
if your_big_query cached table is empty or nearing expiration:
refresh in the background:
check flag to see if there's another "refresh" process running
if yes
end // don't run two your_big_queries at the same time
else
set flag
re-run your_big_query, save to cached table
clear flag
serve data to clients always from cached table
答案 1 :(得分:2)
在Oracle中,一种简单的方法是“CREATE TABLE sometempname AS SELECT ...”。这将使用select中的结果列创建一个新表。
答案 2 :(得分:1)
不太确定你要求的是什么。
目前您有50个数据库会话。假设您有40个运行长时间运行的查询,剩下10个用于服务其余查询。
您似乎要求的是,您希望那些异步(在后台运行)的40个查询不会堵塞50的连接池。问题是,您是否希望这些40与(可能)另外50个同时运行来自连接池的查询,或者您是否希望它们以某种方式排队?
可以完成排队(查看DBMS_SCHEDULER和DBMS_JOB)。但是您需要将这些结果提供给其他表并知道如何提供该结果集。老式的方法就是根据请求生成报告,将报告传送到共享驱动器上的目录或通过电子邮件发送。可以是PDF或CSV或Excel。
如果您希望40与50'连接池'设置同时运行,那么您可能最好为长时间运行的查询设置单独的连接池。
您可以查看资源管理器以终止占用时间过长或资源过多的调用。这样,在长时间运行的请求中,快速池不会陷入困境。
答案 3 :(得分:0)
我能想到的Oracle中最通用的方法是创建一个存储过程,将结果集转换为XML,并将其作为CLOB XMLType存储在一个表中,其中包含长时间运行的查询的结果。
您可以从通用结果集here中找到有关生成XML的更多信息。
SQL> select dbms_xmlgen.getxml('select employee_id, first_name,
2 last_name, phone_number from employees where rownum < 6') xml
3 from dual