Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过rowid高效地检索SQLite行_C++_Database_Performance_Sqlite - Fatal编程技术网

C++ 通过rowid高效地检索SQLite行

C++ 通过rowid高效地检索SQLite行,c++,database,performance,sqlite,C++,Database,Performance,Sqlite,我正在使用SQLite的C接口,并且有一些关于rowid字段的基本问题,以及如何有效地从具有已知rowid的任意行集中检索数据。实际上,我有几个相关的问题,所以我会用粗体显示出来。但我的主要问题在最后 我有一张桌子: sqlite3_exec( db, "create table mytable ( value BLOB, value2 TEXT ) )", NULL, NULL, NULL ); 我用230万行填充它。我还在表上创建了两个索引: sqlite3_exec( db, "CREA

我正在使用SQLite的C接口,并且有一些关于rowid字段的基本问题,以及如何有效地从具有已知rowid的任意行集中检索数据。实际上,我有几个相关的问题,所以我会用粗体显示出来。但我的主要问题在最后

我有一张桌子:

sqlite3_exec( db, "create table mytable ( value BLOB, value2 TEXT ) )", NULL, NULL, NULL );
我用230万行填充它。我还在表上创建了两个索引:

sqlite3_exec( db, "CREATE INDEX r_index ON mytable (rowid)", NULL, NULL, &errorMessage );

sqlite3_exec( db, "CREATE INDEX v_index ON mytable (value)", NULL, NULL, &errorMessage );
我知道rowid索引是不必要的。我看到SQLite需要0秒来创建rowid索引,我认为这是因为rowid始终是表上的隐式现有索引,因为表通常是?以rowid顺序存储

在任何情况下,我希望能够通过rowid从该表中快速检索任意行集。我要做的是创建内存中的记录列表:

class MyInMemoryIndexElement
{
public:
    sqlite3_int64 _rowId;
    MyKeyType _key;
}

vector<ObjectsInMemoryIndexElement> inMemoryIndex;

rc = sqlite3_prepare_v2( db, "select rowid, value from mytable" ), -1, &stmt, NULL );

for ( ; sqlite3_step( stmt ) == SQLITE_ROW ; )
{
    MyInMemoryIndexElement e;
    e._rowId = sqlite3_column_int64( stmt, 0 );
    e._key = GetMyKeyFromValueBlob( sqlite3_column_blob( stmt, 1 ) );
    inMemoryIndex.push_back( e );
}
语句迭代绑定到每个已知rowid,需要1.6秒,比读取数据库中的每一行要长得多

因此:

1我是否可以对这种方法进行一些小的改变,例如,一些其他的索引、操作顺序等,以加快速度

2.这种做法是否存在根本缺陷

*我应该指出,我确实意识到,像这样创建自己的内存中索引违背了我应该将查询规划留给SQL引擎本身的想法。我这样做是因为一般来说,我决定在给定时间感兴趣的记录的逻辑(如上面代码中MySpecialFunction所表示的)比我认为的SQL逻辑更复杂。我愿意接受我需要重新考虑的想法。但就目前而言,我的问题只是关于这样一个事实:从已知rowid中读取14k条记录比读取所有230万条记录花费的时间要长得多,这似乎令人惊讶

更新/解决方案

下面是我根据pm100的建议添加的代码,它将读取14000行的时间缩短到了0.19秒。这仍然超过了读取230万条完整记录所需时间的1/3,但我接受了

请注意,inMemoryIndex已按_rowId排序

sqlite3_intarray *intArrayPointer1;

sqlite3_intarray_create( db, "int_array_1", &intArrayPointer1 );

vector<sqlite3_int64> v;
for ( int i = 0 ; i < inMemoryIndex.size() ; i++ )
{
    if ( MySpecialFunction( inMemoryIndex[ i ]._key ) )
    {
        v.push_back( inMemoryIndex[ i ]._rowId );
    }
}

sqlite3_intarray_bind( intArrayPointer1, v.size(), &v[ 0 ], NULL );

sqlite3_stmt *stmt;
sqlite3_prepare_v2( db, "select value from mytable where rowid in int_array_1", -1, &stmt, NULL );

for ( ; sqlite3_step( stmt ) == SQLITE_ROW ; )
{
    const void *blob = sqlite3_column_blob( stmt, 0 );
    // ... work with "value" blob as you wish
}

有一个代码插件,它使用一个虚拟表来执行您想要的操作


谢谢。我在上面添加了代码,大致显示了我为使用这个int数组扩展所做的代码更改。您知道为什么这个代码在SQLite源代码中命名为test_intarray.c/.h吗?只是InArray概念的创建对于特定的测试集很方便,所以它被称为测试而不是扩展。
"select value from mytable where rowid = ?"
sqlite3_intarray *intArrayPointer1;

sqlite3_intarray_create( db, "int_array_1", &intArrayPointer1 );

vector<sqlite3_int64> v;
for ( int i = 0 ; i < inMemoryIndex.size() ; i++ )
{
    if ( MySpecialFunction( inMemoryIndex[ i ]._key ) )
    {
        v.push_back( inMemoryIndex[ i ]._rowId );
    }
}

sqlite3_intarray_bind( intArrayPointer1, v.size(), &v[ 0 ], NULL );

sqlite3_stmt *stmt;
sqlite3_prepare_v2( db, "select value from mytable where rowid in int_array_1", -1, &stmt, NULL );

for ( ; sqlite3_step( stmt ) == SQLITE_ROW ; )
{
    const void *blob = sqlite3_column_blob( stmt, 0 );
    // ... work with "value" blob as you wish
}