0

我注意到我的 mysql 插入非常慢。为了测试和演示,我使用了下表:

+----------+-----------------------------------------------+
| Table    | Create Table                                  |
+----------+-----------------------------------------------+
| ik_b64_8 | CREATE TABLE `incr_tbl` (
  `cnt` int(11) NOT NULL,
  PRIMARY KEY (`cnt`)
) ENGINE=InnoDB DEFAULT CHARSET=ascii COLLATE=ascii_bin |
+----------+-----------------------------------------------+

和python代码:

def profile_basic(cnt):
    db = database.Connection("localhost","testing_delme","root", "")
    t1 = time.time()
    for ii in range(cnt):
        db.execute("INSERT INTO testing_delme.incr_tbl VALUES (%s)", ii)
    print time.time() - t1

当我在一个空表上运行这个只插入代码时,1K 插入需要 65 秒。我有 innodb_flush_log_at_trx_commit = 1 我需要它,因为表不能丢失任何数据。我的问题是,有了这套,插入会变得这么慢吗?还是我还缺少其他东西?

4

3 回答 3

1

“不能丢失任何数据。” 这只是程度的问题。如果不刷新,您可能会丢失最后一秒的数据。使用刷新,您可能只会丢失当时正在写入的内容。你真的想为此大受打击吗?

此外,如果您的磁盘损坏,无论如何您都会丢失自上次备份以来的所有数据,从长远来看这是不可避免的并且涉及更多数据,因此我更担心进行频繁备份。

禁用冲洗。我认为由于所有磁盘活动,每次插入很容易花费数十甚至数百毫秒。表上有一些索引会使情况变得更糟。

尽管如此,如果您绝对必须在每次写入时刷新,那么如果您将数据库放在 SSD 上,您也会看到性能大幅提升。

于 2012-05-01T20:30:19.507 回答
0

我认为您达到了每秒事务数的限制。您的每个插入都被视为一个单独的事务,您必须处于自动提交模式。

(1) 在一条 SQL 语句中插入多行,就可以了:

insert into incr_tbl values (1),(2),(3)....

Python 等价物是这样的:

db.execute("insert into incr_tbl values %s" % ",".join(["(%s)" % i for i in range(xx)]))

(2) 或者,您可以显式启动事务:

db = ...(autocommit=False)
db.begin_transaction()
for i in xx: db.execute(... insert i ...)
db.commit()

如果你有一台不错的服务器,你的 tx 速率应该远高于每秒 15 次,所以检查你的机器和 mysql 设置。即使您每次都提交到磁盘并等待(sqlite),您应该在商品硬盘上达到 100 tx/s。当数据库位于 USB 闪存时,我只看到过这么低的速率。另一个可能的解释是你的 python 离数据库很远,网络延迟会影响性能,在这种情况下(1)有帮助,(2)没有。

于 2012-12-20T12:52:57.400 回答
0

随着db.execute()你一个一个地插入,它会很慢。使用循环建立一个列表,然后做一个批量插入,即db.executemany()

def profile_basic(cnt):
    import mysql.connector, time
    cnx = mysql.connector.connect("localhost","testing_delme","root", "")
    db = cnx.cursor()
    list_ii = []
    t1 = time.time()
    for ii in range(cnt):
        list_ii.append(ii)
    # One bulk insert
    db.executemany("INSERT INTO testing_delme.incr_tbl VALUES (%s)", list_ii)
    # Don't forget to commit
    db.commit()
    print time.time() - t1 
于 2015-02-15T07:36:11.073 回答