2014-09-10 8 views
7

Używam modułu SQL Qt 5.3.1 (Win 7, VS2013) do wstawiania danych do bazy danych MySQL 5.6. Po zauważeniu pewnych problemów z wydajnością wykonuję trzy testowe fragmenty kodu i mierzy ich środowisko wykonawcze, aby lepiej zrozumieć wydajność SQL. Wynik jest mylący.Wydajność przy korzystaniu z trybu wsadowego Qt/MySQL

Do testowania użyłem tabeli "testowej" zawierającej kolumnę VARCHAR "test" i unikalnie zwiększany identyfikator dla każdego wiersza.

Pierwszy fragment wygląda w zasadzie tak:

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

Drugi tak:

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

Trzecia tak:

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

I wykonany każdy z tych fragmentów (łącznie z kodem otwartym/zamkniętym) 10 razy:

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 

"Delta końcówek" to czas potrzebny na każdy fragment. "Delta jądra" i "User delta" to faktycznie aktywny czas przetwarzania użytkownika i jądra, podczas gdy "Process delta" to suma czasu jądra i użytkownika.

Pierwszy wynik jest zgodny z oczekiwaniem: Potrzeba dużo czasu (zwłaszcza ze względu na opóźnienia), aby wykonać pojedyncze zapytania 10x1000.

Drugi wynik również jest taki, jak oczekiwano: bardzo szybko można wykonać pojedyncze zapytanie zawierające wszystkie wiersze naraz.

Niestety trzeci wynik całkowicie mnie myli: Spodziewałem się, że tryb wsadowy będzie znacznie szybszy! Nawet w najgorszym przypadku (jeśli wykonanie wsadu jest symulowane przez sterownik za pomocą pojedynczych zapytań, jak mówi dokumentacja Qt), powinien on być równie wolny jak pierwszy fragment. W rzeczywistości potrzebuje dwa razy więcej czasu!

Co właściwie robi wykonanie wsadowe w Qt/MySQL? Czy istnieje sposób na poprawę wydajności wymuszania wsadowego? Jak to możliwe, że execBatch() działa o wiele gorzej niż wykonywanie pojedynczych zapytań?

+0

Czy możesz w dowolnym czasie ustawić wartość 'bind_value()'? Nie w pełni rozumiem trzecie podejście, ale wydaje się niezwykłe wiązanie obiektu listy ciągów do parametru SQL. Mogą być dodatkowe warstwy analizy po stronie klienta, których nie widzisz. –

+0

Wywołania bindowania są zwracane niemal natychmiast. – Silicomancer

Odpowiedz

1

QMYSQL nie obsługuje BatchExec.

Możesz użyć QSqlDriver :: hasFeature (QSqlDriver :: BatchOperations), aby sprawdzić, czy sterownik obsługuje Batchexec.

Można również sprawdzić źródło w QT_SRC/src/sql/drivers/mysql/qsql_mysql.cpp

bool QMYSQLDriver :: hasFeature (DriverFeature f) const

to właśnie wrócił fałszywe.

+0

Wygląda na to, że masz rację. Zakładam, że Qt będzie obsługiwać operacje wsadowe, jeśli baza danych to zrobi. AFAIK MySQL obsługuje to. Jaka szkoda. Wciąż zastanawiam się, dlaczego symulowane operacje wsadowe są znacznie wolniejsze niż pojedyncze zapytania. Czy masz pomysł, dlaczego? – Silicomancer

Powiązane problemy