【问题标题】:Performance when using batch mode of Qt / MySQL使用 Qt / MySQL 的批处理模式时的性能
【发布时间】: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


【解决方案1】:

QMYSQL 不支持 BatchExec。

您可以使用 QSqlDriver::hasFeature(QSqlDriver::BatchOperations) 来检查驱动程序是否支持 Batchexec。

也可以查看QT_SRC/src/sql/drivers/mysql/qsql_mysql.cpp中的源码

bool QMYSQLDriver::hasFeature(DriverFeature f) const

它只是返回 false。

【讨论】:

  • 看来你是对的。如果数据库支持,我假设 Qt 将支持批处理操作。 AFAIK MySQL 支持它。真可怜。我仍然想知道为什么模拟批处理操作比单个查询慢得多。你知道为什么吗?
猜你喜欢
  • 2015-12-07
  • 2010-12-17
  • 1970-01-01
  • 2011-07-11
  • 2020-02-12
  • 2015-12-06
  • 1970-01-01
  • 2011-11-17
  • 1970-01-01
相关资源
最近更新 更多