Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.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
Performance PostgreSQL如何比SQLite更快地执行写操作?_Performance_Sqlite_Postgresql_Clojure - Fatal编程技术网

Performance PostgreSQL如何比SQLite更快地执行写操作?

Performance PostgreSQL如何比SQLite更快地执行写操作?,performance,sqlite,postgresql,clojure,Performance,Sqlite,Postgresql,Clojure,我做了一个简单的整数更新性能测试。SQLite每秒仅更新15次,而PostgreSQL每秒更新1500次 SQLite案例的数字似乎是 SQLite站点中的解释似乎是旋转磁盘的一个基本限制 实际上,SQLite可以轻松地在每个数据库中执行50000条或更多INSERT语句 在普通台式电脑上排名第二。但它只能做几十件事 每秒事务数。事务处理速度受 磁盘驱动器的旋转速度。交易通常需要 磁盘盘片的两次完整旋转,在7200RPM的磁盘上 驱动器限制您每秒处理大约60个事务。交易 速度受磁盘驱动器速度限制

我做了一个简单的整数更新性能测试。SQLite每秒仅更新15次,而PostgreSQL每秒更新1500次

SQLite案例的数字似乎是

SQLite站点中的解释似乎是旋转磁盘的一个基本限制

实际上,SQLite可以轻松地在每个数据库中执行50000条或更多INSERT语句 在普通台式电脑上排名第二。但它只能做几十件事 每秒事务数。事务处理速度受 磁盘驱动器的旋转速度。交易通常需要 磁盘盘片的两次完整旋转,在7200RPM的磁盘上 驱动器限制您每秒处理大约60个事务。交易 速度受磁盘驱动器速度限制,因为(默认情况下)SQLite 实际上,等待数据真正安全地存储在磁盘上 在事务完成之前显示。那样的话,如果你突然 断电或操作系统崩溃时,数据仍然安全。对于 详细信息,请阅读SQLite中的原子提交

默认情况下,每个INSERT语句都是它自己的事务。但是如果你 用BEGIN…COMMIT环绕多个INSERT语句,然后使用所有 插入被分组到单个事务中。需要的时间 提交事务在所有随附的插入中摊销 语句,因此每个insert语句的时间大大减少

另一个选项是运行PRAGMA synchronous=OFF。此命令将 使SQLite不等待数据到达磁盘表面,这将 使写操作看起来快得多。但是如果你失去了权力 在事务的中间,您的数据库文件可能损坏。

这是真的吗?那么,PostgreSQL如何能比SQLite执行得更快呢? (我在PostgreSQL中将
fsync
synchronous\u commit
选项设置为
on

更新:

以下是用Clojure编写的完整测试代码:

(defproject foo "0.1.0-SNAPSHOT"
  :repositories {"sonatype-oss-public" "https://oss.sonatype.org/content/groups/public/"}
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [org.clojure/java.jdbc "0.3.0-SNAPSHOT"]
                 [com.mchange/c3p0 "0.9.2.1"]
                 [org.xerial/sqlite-jdbc "3.7.2"]
                 [postgresql "9.1-901.jdbc4"]])
输出为:

; Running "select * from foo" 20000 times in SQLite

"Elapsed time: 1802.426963 ms (11,096 ops)"
"Elapsed time: 1731.118831 ms (11,553 ops)"
"Elapsed time: 1749.842658 ms (11,429 ops)"

; Running "update foo set bar=bar+1 where id=1" 100 times in SQLite

"Elapsed time: 6362.829057 ms (15 ops)"
"Elapsed time: 6405.25075 ms (15 ops)"
"Elapsed time: 6352.943553 ms (15 ops)"

; Running "select * from foo" 20000 times in PostgreSQL

"Elapsed time: 2898.636079 ms (6,899 ops)"
"Elapsed time: 2824.77372 ms (7,080 ops)"
"Elapsed time: 2837.622659 ms (7,048 ops)"

; Running "update foo set bar=bar+1 where id=1" 5000 times in PostgreSQL

"Elapsed time: 3213.120219 ms (1,556 ops)"
"Elapsed time: 3564.249492 ms (1,402 ops)"
"Elapsed time: 3280.128708 ms (1,524 ops)"
pg_fsync_测试结果:

C:\temp>"C:\Program Files\PostgreSQL\9.3\bin\pg_test_fsync"
5 seconds per test
O_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 8kB write:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                   81199.920 ops/sec      12 usecs/op
        fdatasync                                     n/a
        fsync                              45.337 ops/sec   22057 usecs/op
        fsync_writethrough                 46.470 ops/sec   21519 usecs/op
        open_sync                                     n/a

Compare file sync methods using two 8kB writes:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                   41093.981 ops/sec      24 usecs/op
        fdatasync                                     n/a
        fsync                              38.569 ops/sec   25927 usecs/op
        fsync_writethrough                 36.970 ops/sec   27049 usecs/op
        open_sync                                     n/a

Compare open_sync with different write sizes:
(This is designed to compare the cost of writing 16kB
in different write open_sync sizes.)
         1 * 16kB open_sync write                     n/a
         2 *  8kB open_sync writes                    n/a
         4 *  4kB open_sync writes                    n/a
         8 *  2kB open_sync writes                    n/a
        16 *  1kB open_sync writes                    n/a

Test if fsync on non-write file descriptor is honored:
(If the times are similar, fsync() can sync data written
on a different descriptor.)
        write, fsync, close                45.564 ops/sec   21947 usecs/op
        write, close, fsync                33.373 ops/sec   29964 usecs/op

Non-Sync'ed 8kB writes:
        write                             889.800 ops/sec    1124 usecs/op

假设您使用的是普通硬盘(即没有ssd),则每秒最多可写入50-100次。似乎每秒15次写入的速度稍低,但并非不可能


因此,如果Postgres每秒进行1500次更新,它们要么被写入某个缓冲区/缓存,要么被压缩为一次更新。在不了解更多实际测试的情况下,很难说哪一个是真正的原因,但如果您要打开一个事务,更新一行1500次,然后提交,那么Postgres应该足够聪明,只执行一次对磁盘的“真正”写入。

这取决于它们如何实现快照隔离

SQLite使用文件锁定作为隔离事务的一种手段,只允许在完成所有读取后才命中写入

相比之下,Postgres使用了一种更复杂的方法,称为多币种版本控制(mvcc),它允许多个写入与多个读取并行进行


丹尼斯的答案包含了你需要的所有链接。我会选择一个不太详细但可能更容易理解的答案

Sqlite不使用任何复杂的事务管理器,其中没有隐藏的高级多任务逻辑。它执行你让它执行的东西,完全按照这个顺序。换句话说:它完全按照你告诉它的去做。如果您尝试从两个进程中使用相同的数据库,您将遇到问题

另一方面,PostgreSQL是一个非常复杂的数据库:它有效地支持多个并发读写。把它想象成一个异步系统——你只安排要完成的工作,实际上你并不控制它的细节——Postgres为你做这件事


如何提高您的效率?在一个事务中加入几个-几十个-数百个更新/插入。对于一个简单的表,您将获得非常好的性能。

您的怀疑是正确的。具有您指定的设置的PostgreSQL不应能够以每秒1500次的单独顺序事务对旋转介质执行任何更新

您的IO堆栈中可能存在关于如何实现同步的谎言或错误。这意味着您的数据在意外断电或操作系统故障后有严重损坏的风险


从pg_test_fsync的结果来看,情况确实如此。open_datasync是Windows下的默认值,它的速度似乎不现实,因此肯定不安全。当我在Windows7机器上运行pg_test_fsync时,我看到了同样的情况。

实际上,旋转磁盘上的任何写入都是10毫秒量级的(典型数字是8毫秒)

这意味着,如果您在磁盘中写入相同的位置,则每秒写入的次数略多于100次,这对于数据库来说是一种非常奇怪的情况。请参阅ACM中的“您不知道jack关于磁盘的情况”,通常一个磁盘可以在一次循环中安排10次读写


因此,一个数据库每秒可以执行1000次写入,甚至更多。10年前,我在台式计算机上看到过每秒执行1500个事务的应用程序。

这与写入(提交)磁盘的速度(或延迟)无关。它是关于有序写入的。您使用PosgreSQL在每个事务中进行了多少次更新?一个简单的整数更新性能测试:好的,所以我们不知道您实际做了什么。@CL。我没有显式使用事务,所以它是每个事务一次更新。我知道我可以在一个事务中包装多个更新以提高速度,但这不是我现在要问的问题。@DanielVérité这是一个包含两个整数列的表,查询为
update foo set bar=bar+1,其中id=1
我相信它实际上与事务隔离相关的问题有关。@Denis:非常正确,最重要的是,只有在提交之后才能保证何时所有内容都必须写入磁盘。同时,它取决于事务隔离级别。阅读
C:\temp>"C:\Program Files\PostgreSQL\9.3\bin\pg_test_fsync"
5 seconds per test
O_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 8kB write:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                   81199.920 ops/sec      12 usecs/op
        fdatasync                                     n/a
        fsync                              45.337 ops/sec   22057 usecs/op
        fsync_writethrough                 46.470 ops/sec   21519 usecs/op
        open_sync                                     n/a

Compare file sync methods using two 8kB writes:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                   41093.981 ops/sec      24 usecs/op
        fdatasync                                     n/a
        fsync                              38.569 ops/sec   25927 usecs/op
        fsync_writethrough                 36.970 ops/sec   27049 usecs/op
        open_sync                                     n/a

Compare open_sync with different write sizes:
(This is designed to compare the cost of writing 16kB
in different write open_sync sizes.)
         1 * 16kB open_sync write                     n/a
         2 *  8kB open_sync writes                    n/a
         4 *  4kB open_sync writes                    n/a
         8 *  2kB open_sync writes                    n/a
        16 *  1kB open_sync writes                    n/a

Test if fsync on non-write file descriptor is honored:
(If the times are similar, fsync() can sync data written
on a different descriptor.)
        write, fsync, close                45.564 ops/sec   21947 usecs/op
        write, close, fsync                33.373 ops/sec   29964 usecs/op

Non-Sync'ed 8kB writes:
        write                             889.800 ops/sec    1124 usecs/op