Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 如何在没有事务的情况下使用Oracle?_Database_Performance_Oracle_Transactions_Myisam - Fatal编程技术网

Database 如何在没有事务的情况下使用Oracle?

Database 如何在没有事务的情况下使用Oracle?,database,performance,oracle,transactions,myisam,Database,Performance,Oracle,Transactions,Myisam,MySQL具有不支持事务的特殊表类型MyISAM。甲骨文有这样的东西吗?我想创建一个只写数据库(用于日志记录),它需要非常快(将存储大量数据)并且不需要事务。对于类似的情况,我会做的是将日志写入一个文件(附加到文件可能是存储日志的最快方式)然后让一个批处理程序定期将这些日志插入数据库。当然,除非直接插入数据库足够快。。。但是您必须测试…最接近的方法可能是创建一个NOLOGGING表空间,并使用NOLOGGING选项在其中创建表-尽管这可能只适用于批量操作(即需要INSERT/*+APPEND*/

MySQL具有不支持事务的特殊表类型MyISAM。甲骨文有这样的东西吗?我想创建一个只写数据库(用于日志记录),它需要非常快(将存储大量数据)并且不需要事务。

对于类似的情况,我会做的是将日志写入一个文件(附加到文件可能是存储日志的最快方式)然后让一个批处理程序定期将这些日志插入数据库。当然,除非直接插入数据库足够快。。。但是您必须测试…

最接近的方法可能是创建一个NOLOGGING表空间,并使用NOLOGGING选项在其中创建表-尽管这可能只适用于批量操作(即需要INSERT/*+APPEND*/hint)

这将删除重做,如果数据库宕机,将以丢失完整性和数据为代价

我不知道它实际上是“更快”的,你也应该考虑并发(如果你有很多进程试图写入同一个表,那么你可以更好的使用写挂起的更新到重做日志中的事务,而不是尝试全部更新‘真实表’。” 不过,我还没有真正研究过NOLOGGING——我很少遇到应用程序瓶颈是插入速度的问题——当我研究过时,问题出在更新索引的成本上,而不是表

我刚刚做了一个快速测试,在我动力不足的开发数据库上(启用了重做)。为每一行使用一个自治事务—因此每一行开始一个新事务并以提交结束,我可以在1秒内将1000多行写入/提交到一个索引日志表中,而在不提交的情况下执行1000次插入大约需要.875秒

使用批量操作在一次点击中插入1000行只需几秒钟,因此,如果您可以将日志批量化,就可以这样做

其他一些想法:
外部表是否可以完成这项工作?例如,写入日志文件,然后在需要读取时将其作为Oracle中的外部表装载?

这似乎是一种解决问题的方法

你有没有对业绩进行基准测试?甲骨文的速度够快吗?事务管理内置于Oracle的工作方式中,试图绕过它似乎是在为自己创造工作


您似乎已经将事务管理视为一个问题,而不知道是否存在问题。当桌上有多个书写器时,以后会发生什么?还是读卡器阻止写卡器?

事务是SQL数据库操作的关键。它们无疑是甲骨文的基础。如果不发出commit,就无法永久写入Oracle表,而且lo!这就是交易

Oracle允许我们指定要取消记录的表,这不会生成重做日志。这仅适用于批量加载(使用
INSERT/*+APPEND*/
提示),建议切换到日志记录并尽快返回。因为未记录的数据是不可恢复的。如果你不想恢复它,为什么一开始就要写呢

另一种方法是对内存中的写入进行批处理,然后使用大容量插入进行写入。这相当快

以下是一个简单的日志表和一个概念验证包:

create table log_table
(ts timestamp(6)
 , short_text varchar(128)
 , long_text varchar2(4000)
 )
 /

create or replace package fast_log is
     procedure init;
     procedure flush;
     procedure write (p_short log_table.short_text%type
                      , p_long log_table.long_text%type);
end fast_log;
/
日志记录保存在PL/SQL集合中,该集合是具有会话作用域的内存中结构。INIT()过程初始化缓冲区。FLUSH()过程将缓冲区的内容写入LOG_表。WRITE()过程在缓冲区中插入一个条目,如果缓冲区具有所需数量的条目,则调用FLUSH()

写入日志表使用自治的_事务pragma,因此提交不会影响触发刷新的周围事务

对DBMS_OUTPUT.PUT_LINE()的调用是为了便于监控进度。那么,让我们看看它有多快

SQL> begin
  2      fast_log.flush;
  3      for r in 1..3456 loop
  4          fast_log.write('SOME TEXT', 'blah blah blah '||to_char(r));
  5      end loop;
  6      fast_log.flush;
  7  end;
  8  /
FLUSH::12:32:22.640000::0
FLUSH::12:32:22.671000::1000
FLUSH::12:32:22.718000::1000
FLUSH::12:32:22.749000::1000
FLUSH::12:32:22.781000::456

PL/SQL procedure successfully completed.

SQL>
嗯,0.12秒内录制3456张唱片,还不算太差。这种方法的主要问题是需要刷新缓冲区以收集松散的记录;这是一种疼痛,例如,在一个疗程结束时。如果某个原因导致服务器崩溃,未刷新的记录将丢失。在内存中执行任务的另一个问题是它会消耗内存(durrr),因此我们不能使缓存太大

为了便于比较,我向包中添加了一个过程,该过程在每次调用LOG_表时直接将一条记录插入其中,再次使用自治事务:

 procedure write_each (p_short log_table.short_text%type
                  , p_long log_table.long_text%type)

 is
    pragma autonomous_transaction;
 begin
    insert into log_table values ( systimestamp, p_short, p_long );

    commit;

 end write_each;
以下是它的时间安排:

SQL> begin
  2      fast_log.flush;
  3      for r in 1..3456 loop
  4          fast_log.write_each('SOME TEXT', 'blah blah blah '||to_char(r));
  5      end loop;
  6      fast_log.flush;
  7  end;
  8  /
FLUSH::12:32:44.157000::0
FLUSH::12:32:44.610000::0

PL/SQL procedure successfully completed.

SQL>
众所周知,挂钟计时不可靠,但批处理方法比单记录方法快2-3倍。即便如此,我也可以在不到半秒钟的时间内,在一台笔记本电脑上执行三千多个离散事务。所以,问题是:日志记录有多大的瓶颈


为避免任何误解:

@JulesLt在我进行PoC时发布了他的答案。虽然我们的观点有相似之处,但我认为建议的解决方法的差异值得发表这篇文章


“每次写作的时间是什么 没有自主,只有一个 在最后承诺?我的时间安排表明 这并不重要——那就是膨胀 插入是一大胜利”

我的时间安排暗示了一些稍微不同的事情。将每次写入的提交替换为最后的一次提交,所用时间大约为所用时间的一半。仍然比庞大的方法慢,但没有那么多

这里的关键是基准测试。我的概念验证运行速度大约是Jules测试的六倍(我的表有一个索引)。这可能有各种各样的原因——机器规格、数据库版本(我使用的是Oracle11GR1)、表结构等等,换句话说,YMMV

所以教学是:首先决定什么
SQL> begin
  2      fast_log.flush;
  3      for r in 1..3456 loop
  4          fast_log.write_each('SOME TEXT', 'blah blah blah '||to_char(r));
  5      end loop;
  6      fast_log.flush;
  7  end;
  8  /
FLUSH::12:32:44.157000::0
FLUSH::12:32:44.610000::0

PL/SQL procedure successfully completed.

SQL>
CREATE OR REPLACE FUNCTION FNC_LOG(p_log_text varchar2(4000))
 RETURN NUMBER
 IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  -- Your brief code goes here (don't abuse the evil feature that is autonomous transactions).
END;