2014-09-10 10 views
7

Utilizzo il modulo SQL di Qt 5.3.1 (Win 7, VS2013) per inserire dati in un database MySQL 5.6. Dopo aver notato alcuni problemi di prestazioni, ho eseguito tre snippet di codice di test e misurato il loro runtime per ottenere una migliore comprensione delle prestazioni SQL. Il risultato è confuso.Prestazioni quando si utilizza la modalità batch di Qt/MySQL

Per il test, ho utilizzato una tabella "test" contenente una colonna VARCHAR "test" e un ID incrementato in modo univoco per ogni riga.

Il primo frammento appare sostanzialmente simili:

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

La seconda simili:

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

La terza simili:

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

ho eseguito ciascuno di questi frammenti (incluso codice di apertura/chiusura) 10 volte:

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" è il tempo necessario per ciascun snippet. "Delta del kernel" e "Delta utente" sono il tempo di elaborazione del kernel e dell'utente effettivamente attivo mentre "Delta del processo" è la somma del tempo del kernel e dell'utente.

Il primo risultato è come previsto: ha bisogno di molto tempo (soprattutto a causa di latenze) per eseguire query singole 10x1000.

Anche il secondo risultato è come previsto: è molto veloce eseguire una singola query contenente tutte le righe contemporaneamente.

Purtroppo il terzo risultato mi confonde totalmente: mi aspettavo che la modalità batch fosse molto più veloce! Anche nel peggiore dei casi (se l'esecuzione del batch è simulata dal driver che usa singole query come dice la documentazione Qt) dovrebbe essere altrettanto lento del primo frammento. In effetti, ha bisogno il doppio del tempo!

Cosa fa effettivamente l'esecuzione batch in Qt/MySQL? C'è un modo per migliorare le prestazioni di eccitazione batch? Come è possibile che execBatch() funzioni molto peggio dell'esecuzione di singole query?

+0

Puoi cronometrare il pezzo 'bind_value()' in ognuno di questi? Non capisco appieno il terzo approccio, ma mi sembra strano legare un oggetto elenco di stringhe a un parametro SQL. Potrebbero esserci livelli di analisi aggiuntivi sul lato client che non stai vedendo. –

+0

Le chiamate di bind ritornano quasi immediatamente. – Silicomancer

risposta

1

QMYSQL non supporta BatchExec.

È possibile utilizzare QSqlDriver :: hasFeature (QSqlDriver :: BatchOperations) per verificare se un driver supporta Batchexec.

È inoltre possibile controllare la sorgente in QT_SRC/src/sql/drivers/mysql/qsql_mysql.cpp

bool QMYSQLDriver :: hasFeature (DriverFeature f) const

è appena tornato falsa.

+0

Sembra che tu abbia ragione. Supponevo che Qt supportasse le operazioni batch se il database lo fa. AFAIK MySQL lo supporta. Che peccato. Mi chiedo, tuttavia, perché le operazioni batch simulate siano molto più lente delle singole query. Hai un'idea del perché? – Silicomancer

Problemi correlati