如何调整Vertica ODBC驱动程序的性能?

时间:2014-12-02 02:36:40

标签: c odbc vertica unixodbc

我正在使用Vertica ODBC驱动程序(最新的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 秒。对于MySQL,相同的操作将花费不到1秒的时间(客户端和服务器在不同的计算机上运行,​​并且自动提交已关闭)。

检查vertica ODBC日志后,我找到以下日志:

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')

我怀疑&#34; VQueryExecutor::InitializePreparedExecutor: can't promote to streaming&#34;将减慢操作,但谷歌搜索后,没有找到任何有价值的信息。

有人能提供一些关于调优Vertica ODBC驱动程序性能的线索吗?非常感谢提前!

2 个答案:

答案 0 :(得分:2)

我没有使用Vertica的经验,但是您使用ODBC代码和使用ODBC API效率很低。您为每个插入构造了insert语句,这将导致数据库每次都解析它。一个更好的策略是准备(SQLPrepare)插入一次像这样“插入测试(名称,城市)值(?,?)”然后绑定参数(SQLBindParam)和最后(在循环中)调用SQLExecute。此外,您浪费时间分配和释放语句句柄。

答案 1 :(得分:1)

您的糟糕表现可能与您的ODBC设置无关。

你说你想用Vertica和Mysql测试相同的代码,但它们是2种非常不同的数据库,并且对于相同的用例不能以相同的方式有效地使用。

Vertica意味着并行连接几个(10s),每个都做很多工作,例如批量加载大量数据,典型的分析负载。

Mysql意味着并行连接很多(100s,1000s),并没有太多(单个INSERT,单个SELECT),典型的OLTP加载。

也就是说,Vertica符合SQL标准,你的陈述也会起作用,尽管你注意到的速度很慢。如果您使用COPY语句而不是循环INSERT,您会看到一个巨大的差异。即便如此,1000行并不多。使用Vertica的连接设置比mysql慢,如果要加载50k或100k行,那么Vertica的强度与mysql的比较就会变得明显。