Как настроить производительность драйвера Vertica ODBC?

Я использую драйвер ODBC Vertica (новейшая версия 7.1.1) и хочу проверить его производительность.

После обращения к некоторым материалам я настраиваю следующие параметры в odbc.ini:

TransactionIsolation = Read Committed
AutoCommit = 0  

Приложение порождает 20 потоков, и каждый поток будет выполнять 1000 операций вставки. Для каждого потока он будет зафиксирован один раз для 20 операций вставки. Код выглядит так:

......
#define LOOP_COUNT (1000)
#define COMMIT_COUNT (20)

for (i = 0; i < LOOP_COUNT / COMMIT_COUNT; i++)
{
    ret = SQLAllocHandle(SQL_HANDLE_STMT, conn_handle, &stmt_handle);
    if (!SQL_SUCCEEDED(ret))
    {
        printf("Allocate statement handle failed\n");
        goto TEST_THREAD_END; 
    }

    snprintf(sql, sizeof(sql), "insert into test(name, city) values('Nan', 'Nanjing')");
    for (j = 0; j < COMMIT_COUNT; j++)
    {
        ret = SQLExecDirect(stmt_handle, (SQLCHAR*)sql, SQL_NTS);
        if (!SQL_SUCCEEDED(ret))
        {
            printf("Execute statement failed\n");
            goto TEST_THREAD_END; 
        }
    }

    SQLEndTran(SQL_HANDLE_DBC, conn_handle, SQL_COMMIT);

    ret = SQLFreeHandle(SQL_HANDLE_STMT, stmt_handle);
    if (!SQL_SUCCEEDED(ret))
    {
        printf("Free statement handle failed\n");
        goto TEST_THREAD_END; 
    }
}
......

Но тестовая операция очень расстраивает: клиент и сервер работают на одной машине, и вся операция займет около 55 секунд. Та же операция займет менее 1 секунды для MySQL (клиент и сервер работают на разных машинах, и автоматическая фиксация отключена).

После проверки журнала ODBC Vertica я обнаружил следующие журналы:

Dec 02 09:41:26 INFO  3747604224 VDataEngine::Prepare: Original Query: insert into test(name, city) values('Nan', 'Nanjing')
Dec 02 09:41:26 INFO  3747604224 VDataEngine::Prepare: Query is issued as ExecDirect
Dec 02 09:41:26 INFO  3747604224 VDataEngine::Prepare: Query: insert into test(name, city) values('Nan', 'Nanjing')
Dec 02 09:41:26 INFO  3747604224 VDataEngine::Prepare: Initializing prepared statement: _PLAN0x7f7694019de0_0
Dec 02 09:41:26 INFO  3747604224 VQueryExecutor::InitializePreparedExecutor: can't promote to streaming: COPY public.test ( 
name AS 'Nan', city AS 'Nanjing' ) FROM LOCAL STDIN NATIVE VARCHAR ENFORCELENGTH RETURNREJECTED AUTO NO COMMIT
Dec 02 09:41:27 INFO  3747604224 StatementState::InternalPrepare: Preparing query: insert into test(name, city) values('Nan'
, 'Nanjing')
Dec 02 09:41:27 INFO  3747604224 VDataEngine::Prepare: Original Query: insert into test(name, city) values('Nan', 'Nanjing')
Dec 02 09:41:27 INFO  3747604224 VDataEngine::Prepare: Query is issued as ExecDirect
Dec 02 09:41:27 INFO  3747604224 VDataEngine::Prepare: Query: insert into test(name, city) values('Nan', 'Nanjing')
Dec 02 09:41:27 INFO  3747604224 VDataEngine::Prepare: Initializing prepared statement: _PLAN0x7f7694028890_1
Dec 02 09:41:27 INFO  3747604224 VQueryExecutor::InitializePreparedExecutor: can't promote to streaming: COPY public.test ( 
name AS 'Nan', city AS 'Nanjing' ) FROM LOCAL STDIN NATIVE VARCHAR ENFORCELENGTH RETURNREJECTED AUTO NO COMMIT
Dec 02 09:41:27 INFO  3747604224 StatementState::InternalPrepare: Preparing query: insert into test(name, city) values('Nan'
, 'Nanjing')

Я сомневаюсь, что "VQueryExecutor::InitializePreparedExecutor: can't promote to streaming" замедлит работу, но после поиска в Google никакой ценной информации не найти.

Кто-нибудь может подсказать, как настроить производительность драйвера Vertica ODBC? Большое спасибо заранее!


person Nan Xiao    schedule 02.12.2014    source источник
comment
Планируете ли вы выполнять 1000 операторов INSERT каждую секунду? Если да, вам нужно выполнить пакетную загрузку. Может быть, вам лучше использовать JMeter?   -  person Kermit    schedule 02.12.2014
comment
@Kermit: наше приложение будет использовать как Vertica, так и MySQL, поэтому я хочу использовать одну копию кода для работы с обоими, просто изменил DSN в ODBC.ini. После тестирования производительность драйвера MySQL ODBC очень хорошая, никаких дополнительных настроек не требуется. Но Vertica кажется очень медленным. Насколько я понимаю, несмотря на отсутствие некоторых оптимизаций конфигурации, производительность Vertica ODBC не должна быть намного меньше, чем MySQL. Но теперь производительность ODBC Vertica примерно в 100 раз ниже, чем у MySQL. Я думаю, это невозможно понять.   -  person Nan Xiao    schedule 02.12.2014
comment
Если вы являетесь клиентом Vertica, попробуйте обратиться в службу поддержки, если вы не получите здесь хороших ответов. В противном случае попробуйте сообщество Vertica.   -  person Kermit    schedule 02.12.2014


Ответы (2)


Ваша плохая производительность, вероятно, не имеет ничего общего с вашей настройкой ODBC.

Вы говорите, что хотите протестировать один и тот же код с помощью Vertica и Mysql, но это две совершенно разные базы данных, и их нельзя эффективно использовать одинаково для одного и того же варианта использования.

Vertica предназначена для нескольких (10) подключений параллельно, каждое из которых выполняет много работы, например, пакетная загрузка большого количества данных, типичная загрузка аналитики.

Mysql предназначен для того, чтобы иметь много (100, 1000) параллельных подключений, не делая много (один INSERT, один SELECT), типичные нагрузки OLTP.

Тем не менее, Vertica совместима с SQL, и ваше утверждение будет работать, хотя и медленно, как вы заметили. Если бы вы использовали оператор COPY вместо цикла INSERT, вы бы увидели огромную разницу. Даже тогда 1000 строк — это немного. Установка соединения с Vertica медленнее, чем с mysql, и если бы вы загрузили, скажем, 50 или 100 тысяч строк, то стало бы очевидно, в чем сила Vertica по сравнению с mysql.

person Guillaume    schedule 02.12.2014
comment
Потрясающее объяснение! Большое спасибо! Но для информации: VQueryExecutor::InitializePreparedExecutor: can't promote to streaming: COPY public.test (name AS 'Nan', city AS 'Nanjing' ) FROM LOCAL STDIN NATIVE VARCHAR ENFORCELENGTH RETURNREJECTED AUTO NO COMMIT, не могли бы вы дать какой-нибудь совет? Я не могу найти никакой ценной информации из Google или руководства. - person Nan Xiao; 02.12.2014
comment
@NanXiao Я не использую C, только Python, поэтому могу только догадываться. Если вы COPY LOCAL FROM STDIN, вам понадобятся 2 потока (один выполняет оператор COPY, а другой передает данные). COPY FROM LOCAL STDIN обычно используется из командной строки или скриптов типа unix. Я бы предложил в качестве теста КОПИРОВАТЬ ЛОКАЛЬНЫЙ «файл», которому не нужен фидер, и посмотреть, есть ли у вас та же ошибка. - person Guillaume; 02.12.2014
comment
Мне кажется, что если отключить автоматическую фиксацию, вы должны сначала использовать SQLPrepare. Но у меня нет никаких ссылок, только предположение. В любом случае, большое спасибо за ваше подробное и любезное объяснение! - person Nan Xiao; 02.12.2014
comment
@NanXiao Вы всегда должны использовать подготовленные операторы. Vertica оптимизирует нагрузку в зависимости от типов данных. - person Kermit; 02.12.2014

У меня нет опыта работы с Vertica, но ваш код C и использование ODBC API неэффективны. Вы создаете свой оператор вставки для каждой вставки, и это заставит базу данных каждый раз анализировать его. Лучшая стратегия состоит в том, чтобы подготовить (SQLPrepare) вставку один раз, например, «вставить в тест (имя, город) значения (?,?)», Затем привязать параметры (SQLBindParam) и, наконец (в цикле), чтобы вызвать SQLExecute. Кроме того, вы тратите время на выделение и освобождение дескриптора оператора.

person bohica    schedule 02.12.2014
comment
Точно! первое, что нужно оптимизировать, это код, который крайне неэффективен. В отличие от драйвера MySQL ODBC, Vertica может запускать пакетные команды INSERT, которые внутренне преобразуются в команду COPY FROM LOCAL. На порядок быстрее, чем любая вставка одной строки. - person mauro; 11.06.2017