【发布时间】:2014-09-11 14:30:54
【问题描述】:
我正在使用 Qt 5.3.1 (Win 7, VS2013) 的 SQL 模块将数据插入 MySQL 5.6 数据库。在我注意到一些性能问题后,我执行了三个测试代码 sn-ps 并测量了它们的运行时间,以更好地了解 SQL 性能。结果令人困惑。
为了测试,我使用了一个“test”表,其中包含一个 VARCHAR 列“test”和每行唯一递增的 id。
第一个 sn-p 基本上是这样的:
const QString uploadQueryString("INSERT INTO test (test) VALUES ('%1')");
for (int i=0; i<1000; i++)
{
QSqlQuery uploadQuery(uploadQueryString.arg("A: test text"), dataBase);
if (uploadQuery.lastError().isValid())
{
qDebug() << tr("Query execution failed (%1)").arg(uploadQuery.lastError().text());
}
}
第二个是这样的:
const QString uploadQueryString("INSERT INTO test (test) VALUES %1");
QStringList values;
for (int j=0; j<1000; j++)
{
values.append("\"B: test text\"");
}
QString valuesString = "("+ContainerToString(values, "), (")+")";
QSqlQuery uploadQuery(uploadQueryString.arg(valuesString), dataBase);
if (uploadQuery.lastError().isValid())
{
qDebug() << tr("Query execution failed (%1)").arg(uploadQuery.lastError().text());
}
第三个是这样的:
const QString uploadQueryString("INSERT INTO test (test) VALUES (:values)");
QVariantList values;
for (int j=0; j<1000; j++)
{
values.append("C: test text");
}
QSqlQuery batchQuery(dataBase);
if (batchQuery.prepare(uploadQueryString))
{
batchQuery.bindValue(":values", values);
if (!batchQuery.execBatch())
{
qDebug() << tr("Batch query execution failed (%1)").arg(batchQuery.lastError().text());
}
}
else
{
qDebug() << tr("Unable to prepare batch query");
}
我对这些 sn-ps(包括打开/关闭代码)中的每一个执行了 10 次:
1. 10x1000 basic inserts
Ticks delta: 318617 ms; Kernel delta: 358 ms; User delta: 1201 ms; Process delta 1559 ms
2. 10x1000 by value list insert
Ticks delta: 3011 ms; Kernel delta: 0 ms; User delta: 46 ms; Process delta 46 ms
3. 10x1000 by batch insert
Ticks delta: 631679 ms; Kernel delta: 811 ms; User delta: 998 ms; Process delta 1809 ms
“Ticks delta”是每个 sn-p 所需的时间。 “Kernel delta”和“User delta”是实际活跃的用户和内核处理时间,而“Process delta”是内核和用户时间的总和。
第一个结果如预期:执行 10x1000 单次查询需要大量时间(尤其是由于延迟)。
第二个结果也如预期:一次执行包含所有行的单个查询非常快。
唉,第三个结果完全让我感到困惑:我预计批处理模式会快得多!即使在最坏的情况下(如果批处理执行是由驱动程序使用单个查询模拟的,如 Qt 文档所述),它应该与第一个 sn-p 一样慢。实际上它需要两倍的时间!
批处理执行在 Qt/MySQL 中实际上做了什么?有没有办法提高批处理执行性能? execBatch() 的性能怎么可能比执行单个查询差得多?
【问题讨论】:
-
你能在这些中对
bind_value()进行计时吗?我不完全理解第三种方法,但是将字符串列表对象绑定到 SQL 参数似乎很不寻常。客户端上可能还有其他您看不到的解析层。 -
绑定调用几乎立即返回。
标签: mysql sql qt database-performance