SQLite R * Tree Module Test

SQLite R * Tree Module Test

Related reference:

Simple to use MySQL spatial index

MongoDB geospatial data storage and retrieval

The SQLite R*Tree Module

Memory-Mapped I/O

In-Memory Databases

libspatialindex

R* tree - Wikipedia

1, SQLite R * Tree module Characteristics Introduction

SQLite space on an index related presentations can view the official document at The SQLite R * Tree Module , here only a brief introduction.

. 1, the SQLite R & lt * Tree module implemented in the source code inside portion ( codes download page ), without additional combined. But the default is not enabled, enable to define SQLITE_ENABLE_RTREE=1macros recompiled.

2, the SQLite R * Tree module virtual table implementation, each R * Tree index is a virtual table. For this table, a first column must be 64-bit signed integer type, as the primary key. Other columns (columns 2-12) is determined according to the spatial dimension, each dimension including a pair of (two), respectively, the minimum and maximum dimension. For example: a virtual-dimensional R * Tree index table contains three, respectively Int64主键| 最小值| 最大值; R * Tree index dimensional virtual table contains 5, respectively Int64主键| 第一维最小值| 第一维最大值| 第二维最小值| 第二维最大值; 3,4,5-dimensional virtual R * Tree index table columns in this case On the push, SQLite R * tree implementation does not support the width dimension of more than 5 R * tree.

3, for each column the maximum and minimum dimensions, SQLite may be used int32or float32the type of data storage. Other conventional different column in the table, this type of memory is a binary value, rather than converted to a string. If the data at the time of insertion, than the use of both types, for implicit conversion occurs.

    -- 创建整型坐标rtree索引虚拟表
    CREATE VIRTUAL TABLE intrtree USING rtree_i32(id,x0,x1,y0,y1,z0,z1);
    -- 创建浮点型坐标rtree索引虚拟表
    CREATE VIRTUAL TABLE floatrtree USING rtree(id,x0,x1,y0,y1,z0,z1);

. 4, the SQLite * R & lt Tree Query Query not limited dimension table must be consistent with the dimensions in the query, the query may be only a few of which dimension (e.g., 3-dimensional spatial query only 2 dimensions). Generally, the more constraints (dimensions), the smaller the range of the block query, the faster.

5, using the default float32coordinate values are stored, can not be accurately represented when the incoming values, the lower limit coordinate rounding down, rounding up the coordinates of the upper limit, so the bounding box may be slightly larger than specified, but never becomes smaller. This is a query outside the scope of data, there may be a very small error.

6, for 3.24.0 previous versions, the SQLite R & lt * Tree index table only stores the virtual integer coordinate values and the primary key column, require additional information saved in another table (by associating a primary key). 3.24.0 version from the start, SQLite R * Tree index virtual table column can store any type of auxiliary data, the auxiliary column must +begin with, can store up to 100 auxiliary columns.

    CREATE VIRTUAL TABLE demo_index2 USING rtree(
       id,              -- 64位整型主键
       minX, maxX,      -- X方向最小最大值
       minY, maxY,      -- Y方向最小最大值
       +objname TEXT,   -- 辅助列 文本类型
       +objtype TEXT,   -- 辅助列 文本类型
       +boundary BLOB   -- 辅助列 二进制数据
    );

7, R-Tree can customize the query, in order to achieve non-collision rectangular frame. This is done by sqlite3_rtree_query_callback(new, started offering 3.8.5) or sqlite3_rtree_geometry_callback(old) Register the SQL query and match detection callback. Related information are described in detail on the SQLite web site.

8, a SQLite R * Tree ship with three shadow table, for storing data, respectively 虚拟表名_node(storage node) 虚拟表名_parent(parent node storage) 虚拟表名_rowid(ROWID storage node).

9, may be used SELECT rtreecheck('虚拟表名')to check the completeness and correctness of the R-Tree index.

2, SQLite R * Tree simple test code module

Write a simple test program to test the speed ** R * Tree ** tree, the result is still possible.

My machine environment:

Windows 10 1903 x64 Professional Edition

AMD Dacentrurus 2600X

DDR4 2400 8G

Compiler: VS2017 Native x64

When the local file, data insertion period is about one hundred thousand within two seconds, a query range of 5x5 size, a time substantially less than 0.07 seconds; memory using mode, the insertion time is within about 1.8 seconds, a query of 5x5 size range, time is substantially less than 0.04 seconds.

Note: When compiling SQLite To define SQLITE_ENABLE_RTREEthe macro, open RTree index support.

#include "sqlite/sqlite3.h"
#include<time.h>
#include <stdlib.h>
#include <stdio.h>

// 因为仅仅是进行一下试用测试,所以有些地方就没有处理,包括close

int main() 
{
    sqlite3* db = NULL;
    int rc = sqlite3_open(":memory:", &db);
    // int rc = sqlite3_open("D:/sqlite_rtree/test.db", &db);
    if (rc != SQLITE_OK) 
    {
        return -1;
    }
    
    char* errmsg;
    // 创建RTree索引虚拟表
    rc = sqlite3_exec(db,
                      "CREATE VIRTUAL TABLE demo_index USING rtree(id,minX, maxX,minY, maxY)",
                      NULL, NULL, &errmsg);
    if (rc != SQLITE_OK) 
    {
        printf("%4d Error:%sn", __LINE__, errmsg);
        return -2;
    }
    
    // 开始计时
    clock_t start = clock();
    
    // 开启事物
    if (sqlite3_exec(db, "begin", NULL, NULL, &errmsg) != SQLITE_OK) {
        printf("%4d Error:%sn", __LINE__, errmsg);
        return -2;
    }
    
    // 生成十万个大小在 边长在[0.002,0.202]度大小以内的数据(0.2~22.5公里左右)
    srand(time(NULL));  // 初始化随机数种子
    sqlite3_stmt *pStmt = NULL;
    
    // 预处理SQL语句
    if(sqlite3_prepare_v2(db,
                          "INSERT INTO demo_index VALUES(?,?,?,?,?)",
                          40, &pStmt, NULL) != SQLITE_OK) {
        printf("%4d Error:%sn", __LINE__, errmsg);
        return -3;
    }
    // 逐个插入
    for (int i = 0; i < 100000; ++i) {
        // 生成在经纬度范围内的x,y
        double x0 = ((double)rand() / (double)RAND_MAX) * 360 - 180;
        double y0 = ((double)rand() / (double)RAND_MAX) * 180 - 90;
        double x1 = x0 + 0.002 + ((double)rand() / (double)RAND_MAX)*0.2;
        double y1 = y0 + 0.002 + ((double)rand() / (double)RAND_MAX)*0.2;
        // 绑定数据
        sqlite3_bind_int(pStmt, 1, i);
        sqlite3_bind_double(pStmt, 2, x0);
        sqlite3_bind_double(pStmt, 3, x1);
        sqlite3_bind_double(pStmt, 4, y0);
        sqlite3_bind_double(pStmt, 5, y1);
        // 执行
        sqlite3_step(pStmt);
        // 重置
        sqlite3_reset(pStmt);
    }
    sqlite3_finalize(pStmt); //结束语句,释放语句句柄
    
    // 结束事物
    if (sqlite3_exec(db, "commit", NULL, NULL, &errmsg) != SQLITE_OK){
        printf("%4d Error:%sn", __LINE__, errmsg);
        return -2;
    }
    
    
    // 结束计时
    clock_t end = clock();
    double hs = (double)(end - start) * 1000 / CLOCKS_PER_SEC;
    printf("插入总耗时: %lf msn", hs);
    // 查询
    // 预处理SQL语句
    pStmt = NULL;
    if (sqlite3_prepare_v2(db,
            "SELECT id,minX,minY FROM demo_index WHERE minX>=? AND maxX<=? AND minY>=?  AND maxY<=?;",
            -1, &pStmt, NULL) != SQLITE_OK) {
        printf("%4d Error:%sn", __LINE__, errmsg);
        return -4;
    }
    
    //-------------------------------------------------------------------------
    
    // 输入查询的范围框数据
    puts("Input x0,x1,y0,y1:");
    double x0, x1, y0, y1;
    scanf("%lf,%lf,%lf,%lf", &x0, &x1, &y0, &y1);
    printf("-----------[%lf,%lf,%lf,%lf]-------------n", x0, x1, y0, y1);
    
    // 开始计时
    start = clock();
    
    // 绑定查询范围数据
    sqlite3_bind_double(pStmt, 1, x0);
    sqlite3_bind_double(pStmt, 2, x1);
    sqlite3_bind_double(pStmt, 3, y0);
    sqlite3_bind_double(pStmt, 4, y1);
    while (sqlite3_step(pStmt) == SQLITE_ROW) {
        int id = sqlite3_column_int(pStmt, 0);
        double x = sqlite3_column_double(pStmt, 1);
        double y = sqlite3_column_double(pStmt, 2);
        printf("%dt %lf,%lfn", id, x, y);
    }
    sqlite3_finalize(pStmt); //结束语句,释放语句句柄
    
    // 结束计时
    end = clock();
    hs = (double)(end - start) * 1000 / CLOCKS_PER_SEC;
    printf("本次查询总耗时: %lf msn", hs);
    
    
    sqlite3_close(db);
    system("pause");
    return 0;
}

Guess you like

Origin www.cnblogs.com/oloroso/p/10941099.html