我注意到我的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,我需要它,因为表不能丢失任何数据。我的问题是,使用此设置,插入是否会变得如此之慢?或者我也错过了其他的东西?
答案 0 :(得分:1)
“不能丢失任何数据。”这只是程度问题。如果没有刷新,您可能会丢失最后一秒的数据。通过刷新,您可能只会丢失当时正在编写的内容。你真的想要在这方面取得巨大的成绩吗?
此外,如果您的磁盘坏了,您将丢失自上次备份以来的所有数据,从长远来看这是不可避免的,并且涉及更多数据,所以我更担心频繁备份。
禁用刷新。我认为,由于所有磁盘活动,每次插入很容易需要几十(如果不是几百毫秒)。在桌面上有一些索引会使情况更糟。
尽管如此,如果你把数据库放在SSD上,你绝对必须在每次写入时都进行刷新,你也会看到很大的性能提升。
答案 1 :(得分: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 flash时,我只看到这个低的速率。另一个可能的解释是你的python离数据库很远,网络延迟会导致性能下降,在这种情况下(1)有帮助,(2)没有。
答案 2 :(得分: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