我正在使用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驱动程序性能的线索吗?非常感谢提前!
答案 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的比较就会变得明显。