Improve sqlite access speed by using rowid in query if possible

The speedup is measurable, but not stellar.
This commit is contained in:
Rogier 2015-02-26 12:01:21 +01:00
parent 7c2cf3efa9
commit 216bc32a35
3 changed files with 39 additions and 16 deletions

View File

@ -34,19 +34,23 @@ struct BlockPos {
//#else
// std::size_t hash(void) const { return databasePosI64() % SIZE_MAX; }
//#endif
BlockPos() : dimension{0, 0, 0}, m_strFormat(Unknown) {}
BlockPos(int _x, int _y, int _z) : dimension{_x, _y, _z}, m_strFormat(Unknown) {}
BlockPos(const BlockPos &pos) : dimension{pos.x(), pos.y(), pos.z()}, m_strFormat(pos.m_strFormat) {}
BlockPos() : dimension{0, 0, 0}, m_strFormat(Unknown), m_id(INT64_MIN) {}
BlockPos(int _x, int _y, int _z) : dimension{_x, _y, _z}, m_strFormat(Unknown), m_id(INT64_MIN) {}
BlockPos(int _x, int _y, int _z, int64_t id) : dimension{_x, _y, _z}, m_strFormat(Unknown), m_id(id) {}
BlockPos(const BlockPos &pos) : dimension{pos.x(), pos.y(), pos.z()}, m_strFormat(pos.m_strFormat), m_id(pos.m_id) {}
BlockPos(int64_t i) { operator=(i); }
BlockPos(int64_t i, int64_t id) { operator=(i); m_id = id; }
BlockPos(const std::string &s) { operator=(s); }
int64_t databasePosI64(void) const { return getDBPos(); }
int64_t databasePosId(void) const { return m_id; }
bool databasePosIdIsValid(void) const { return m_id != INT64_MIN; }
std::string databasePosStr(StrFormat defaultFormat = Unknown) const;
std::string databasePosStrFmt(StrFormat format) const;
bool operator<(const BlockPos& p) const;
bool operator==(const BlockPos& p) const;
void operator=(const BlockPos &p) { x() = p.x(); y() = p.y(); z() = p.z(); m_strFormat = p.m_strFormat; }
void operator=(int64_t i) { setFromDBPos(i); m_strFormat = I64; }
void operator=(const BlockPos &p) { x() = p.x(); y() = p.y(); z() = p.z(); m_strFormat = p.m_strFormat; m_id = p.m_id; }
void operator=(int64_t i) { setFromDBPos(i); m_strFormat = I64; m_id = INT64_MIN; }
void operator=(const std::string &s);
static const int Any = INT_MIN;
@ -62,7 +66,7 @@ protected:
private:
// WARNING: see comment about m_strFormat above !!
StrFormat m_strFormat;
int64_t m_id;
};
struct NodeCoord : BlockPos
@ -117,6 +121,7 @@ namespace std {
inline void BlockPos::operator=(const std::string &s)
{
m_id = INT64_MIN;
std::istringstream is(s);
if (isdigit(is.peek()) || is.peek() == '-' || is.peek() == '+') {
int64_t ipos;

View File

@ -3,15 +3,17 @@
#include <unistd.h> // for usleep
#include "types.h"
#define BLOCKPOSLIST_STATEMENT "SELECT pos FROM blocks"
#define BLOCK_STATEMENT "SELECT pos, data FROM blocks WHERE pos == ?"
#define BLOCKPOSLIST_STATEMENT "SELECT pos, rowid FROM blocks"
#define BLOCK_STATEMENT_POS "SELECT pos, data FROM blocks WHERE pos == ?"
#define BLOCK_STATEMENT_ROWID "SELECT pos, data FROM blocks WHERE rowid == ?"
DBSQLite3::DBSQLite3(const std::string &mapdir) :
m_blocksQueriedCount(0),
m_blocksReadCount(0),
m_blockPosListStatement(NULL),
m_blockOnPosStatement(NULL)
m_blockOnPosStatement(NULL),
m_blockOnRowidStatement(NULL)
{
std::string db_name = mapdir + "map.sqlite";
@ -21,14 +23,18 @@ DBSQLite3::DBSQLite3(const std::string &mapdir) :
if (SQLITE_OK != sqlite3_prepare_v2(m_db, BLOCKPOSLIST_STATEMENT, sizeof(BLOCKPOSLIST_STATEMENT)-1, &m_blockPosListStatement, 0)) {
throw std::runtime_error("Failed to prepare SQL statement (blockPosListStatement)");
}
if (SQLITE_OK != sqlite3_prepare_v2(m_db, BLOCK_STATEMENT, sizeof(BLOCK_STATEMENT)-1, &m_blockOnPosStatement, 0)) {
if (SQLITE_OK != sqlite3_prepare_v2(m_db, BLOCK_STATEMENT_POS, sizeof(BLOCK_STATEMENT_POS)-1, &m_blockOnPosStatement, 0)) {
throw std::runtime_error("Failed to prepare SQL statement (blockOnPosStatement)");
}
if (SQLITE_OK != sqlite3_prepare_v2(m_db, BLOCK_STATEMENT_ROWID, sizeof(BLOCK_STATEMENT_ROWID)-1, &m_blockOnRowidStatement, 0)) {
throw std::runtime_error("Failed to prepare SQL statement (blockOnRowidStatement)");
}
}
DBSQLite3::~DBSQLite3() {
if (m_blockPosListStatement) sqlite3_finalize(m_blockPosListStatement);
if (m_blockOnPosStatement) sqlite3_finalize(m_blockOnPosStatement);
if (m_blockOnRowidStatement) sqlite3_finalize(m_blockOnRowidStatement);
sqlite3_close(m_db);
}
@ -49,7 +55,8 @@ const DB::BlockPosList &DBSQLite3::getBlockPos() {
result = sqlite3_step(m_blockPosListStatement);
if(result == SQLITE_ROW) {
sqlite3_int64 blocknum = sqlite3_column_int64(m_blockPosListStatement, 0);
m_BlockPosList.push_back(blocknum);
sqlite3_int64 rowid = sqlite3_column_int64(m_blockPosListStatement, 1);
m_BlockPosList.push_back(BlockPos(blocknum, rowid));
} else if (result == SQLITE_BUSY) // Wait some time and try again
usleep(10000);
else
@ -64,15 +71,25 @@ DB::Block DBSQLite3::getBlockOnPos(const BlockPos &pos)
{
Block block(pos,reinterpret_cast<const unsigned char *>(""));
int result = 0;
m_blocksQueriedCount++;
sqlite3_bind_int64(m_blockOnPosStatement, 1, pos.databasePosI64());
sqlite3_stmt *statement;
if (pos.databasePosIdIsValid()) {
statement = m_blockOnRowidStatement;
sqlite3_bind_int64(m_blockOnRowidStatement, 1, pos.databasePosId());
}
else {
statement = m_blockOnPosStatement;
sqlite3_bind_int64(m_blockOnPosStatement, 1, pos.databasePosI64());
}
while (true) {
result = sqlite3_step(m_blockOnPosStatement);
result = sqlite3_step(statement);
if(result == SQLITE_ROW) {
const unsigned char *data = reinterpret_cast<const unsigned char *>(sqlite3_column_blob(m_blockOnPosStatement, 1));
int size = sqlite3_column_bytes(m_blockOnPosStatement, 1);
const unsigned char *data = reinterpret_cast<const unsigned char *>(sqlite3_column_blob(statement, 1));
int size = sqlite3_column_bytes(statement, 1);
block = Block(pos, ustring(data, size));
m_blocksReadCount++;
break;
@ -82,7 +99,7 @@ DB::Block DBSQLite3::getBlockOnPos(const BlockPos &pos)
break;
}
}
sqlite3_reset(m_blockOnPosStatement);
sqlite3_reset(statement);
return block;
}

View File

@ -32,6 +32,7 @@ private:
sqlite3 *m_db;
sqlite3_stmt *m_blockPosListStatement;
sqlite3_stmt *m_blockOnPosStatement;
sqlite3_stmt *m_blockOnRowidStatement;
std::ostringstream m_getBlockSetStatementBlocks;
BlockCache m_blockCache;
BlockPosList m_BlockPosList;