2014-09-10 1 views
7

Я использую SQL-модуль Qt 5.3.1 (Win 7, VS2013) для вставки данных в базу данных MySQL 5.6. После того, как я заметил некоторые проблемы с производительностью, я выполнил три фрагмента тестовых кодов и измерил их время выполнения, чтобы лучше понять производительность SQL. Результат запутан.Производительность при использовании пакетного режима Qt/MySQL

Для тестирования я использовал «тестовую» таблицу, содержащую столбец VARCHAR «test» и уникально увеличенный идентификатор для каждой строки.

Первый фрагмент выглядит по существу, как это:

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"); 
} 

я выполнил каждый из этих фрагментов (включая код открытия/закрытия) 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" - это время, необходимое для каждого фрагмента. «Дельта ядра» и «Пользовательская дельта» - фактически активное время обработки пользователя и ядра, а «Дельта процесса» - это сумма времени ядра и пользователя.

Первый результат в ожидании: для выполнения 10x1000 одиночных запросов требуется много времени (особенно из-за задержек).

Второй результат также похож на ожидаемый: очень быстро выполнить один запрос, содержащий все строки одновременно.

Увы, третий результат полностью меня смущает: я ожидал, что пакетный режим будет намного быстрее! Даже в худшем случае (если пакетное исполнение моделируется драйвером с использованием одиночных запросов, например, как описано в документации Qt), он должен быть столь же медленным, как и первый фрагмент. На самом деле это требуется в два раза больше времени!

Что делает пакетное выполнение на самом деле в Qt/MySQL? Есть ли способ улучшить производительность выработки пакетов? Как возможно, что execBatch() выполняет намного хуже, чем выполнение одиночных запросов?

+0

Можете ли вы обработать произведение 'bind_value()' в каждом из них? Я не совсем понимаю третий подход, но кажется необычным связывать объект списка строк с параметром SQL. На стороне клиента могут быть дополнительные слои синтаксического анализа, которые вы не видите. –

+0

Прямые звонки возвращаются почти сразу. – Silicomancer

ответ

1

QMYSQL не поддерживает BatchExec.

Вы можете использовать QSqlDriver :: hasFeature (QSqlDriver :: BatchOperations), чтобы проверить, поддерживает ли драйвер Batchexec.

Вы также можете проверить источник в QT_SRC/SRC/SQL/драйверов/MySQL/qsql_mysql.cpp

BOOL QMYSQLDriver :: hasFeature (DriverFeature е) Const

он только что вернулся ложным.

+0

Кажется, вы правы. Я предположил, что Qt будет поддерживать пакетные операции, если база данных. AFAIK MySQL поддерживает его. Как жаль. Тем не менее я удивляюсь, почему имитированные пакетные операции намного медленнее, чем одиночные запросы. У вас есть идея, почему? – Silicomancer