golang操作sqlite3加速本地结构化数据查询

目录

  • 摘要
  • Sqlite3
    • SQLite 命令
    • SQLite 语法
    • SQLite 数据类型
      • 列亲和类型——优先选择机制
    • SQLite 创建数据库
      • SQLite 附加数据库
      • SQLite 分离数据库
    • SQLite 创建表
      • SQLite 删除表
    • SQLite Insert 语句
    • SQLite Select 语句
      • SQLite 运算符
        • SQLite 算术运算符
        • SQLite 比较运算符
        • SQLite 逻辑运算符
        • SQLite 位运算符
    • SQLite 表达式
  • golang操作sqlite
    • golang操作sqlite3加速本地结构化数据查询
      • SimpleReader
      • MapReader
      • sqlReader
  • 总结
  • 轶闻趣事:SQLite 背后的故事

摘要

在没有网络支持且仅能使用 Go 语言包的开发环境中,如果需要频繁查询一个较大的 CSV 文件,有几种优化方案可以考虑。

  1. 传统的遍历方法

    • 使用 Go 的 csv 库,针对每次查询都遍历整个 CSV 文件。这种方法简单易懂,但性能较差,尤其在数据量较大时,每次查询都需要重新读取整个文件,效率低下。
  2. 将数据加载到内存(Map 存储)

    • 通过一次性读取 CSV 文件并将其存储在内存中的 map 结构中,可以大幅提高查询性能。利用 map 提供的 O(1) 查找时间,查询操作会变得非常迅速。这种方法适用于数据集较小到中等的情况,且查询操作较为简单。需要注意的是,数据量过大会导致内存消耗过高。
  3. 使用 SQLite 存储数据

    • 如果需要更高效的查询,特别是支持更复杂筛选的场景,可以考虑将 CSV 文件的数据导入到 SQLite 中。SQLite 提供了轻量级的 SQL 查询功能,可以通过创建表和索引来加速数据检索,同时支持复杂的查询操作(如筛选、排序、聚合等)。SQLite 不需要单独安装任何服务,直接通过 Go 包 github.com/mattn/go-sqlite3 即可进行操作,适合在 Golang 环境中使用。

每种方法都有其适用场景:对于小数据集和简单查询,map 存储足够快速且轻量;而对于较大数据集或复杂查询,SQLite 提供了更好的查询灵活性和性能。

Sqlite3

SQLite3 是一个开源的、轻量级的关系型数据库管理系统 (RDBMS),它的主要特点是将数据库引擎嵌入到应用程序中,而无需依赖服务器端数据库系统。SQLite3 以其小巧、高效、易于集成和高可靠性成为许多桌面、移动设备及嵌入式系统中常用的数据库解决方案。

SQLite3 的基本特点

  1. 嵌入式数据库
    SQLite3 是一个 嵌入式数据库,意味着它是一个库(.dll 或 .so 文件)而非独立的服务器程序。数据库的所有数据都存储在单一的文件中,应用程序通过链接该库来操作数据库。这使得 SQLite3 在轻量级应用和小型项目中非常流行。

  2. 跨平台支持
    SQLite3 支持几乎所有的操作系统,包括但不限于 Windows、Linux、macOS、iOS、Android 等。由于它是 C 语言编写的,可以轻松地跨平台移植。

  3. 无服务器架构
    SQLite3 是 无服务器的,这意味着没有独立的数据库进程或服务。应用程序直接访问数据库文件,且访问数据库不依赖网络连接。它通过文件系统进行 I/O 操作,查询和写入数据速度非常快。

  4. 事务支持
    SQLite3 完全支持 ACID(原子性、一致性、隔离性、持久性)事务,这意味着它可以确保数据的完整性。在发生崩溃时,SQLite3 会自动回滚到事务开始之前的状态,确保数据的可靠性。

  5. 轻量级
    SQLite3 的二进制文件非常小,通常只有几百 KB(具体大小取决于编译选项)。它不需要配置或安装复杂的数据库服务器,适合于嵌入式应用、小型应用、单用户应用和其他资源有限的系统。

  6. 零配置
    SQLite3 无需安装或配置数据库引擎。只需要包含数据库文件和链接库即可,完全适合于需要零配置的场景。所有数据库设置都是在数据库文件级别进行的。

  7. 自包含
    SQLite3 是 自包含的,它包含了所有的功能。SQLite 的操作和配置不依赖于外部软件或库。SQLite3 将数据库及其管理功能直接集成到应用程序中,进一步简化了使用过程。

SQLite3 的工作原理

SQLite3 将数据存储在单一的文件中,这个文件中不仅存储了数据,还包括了数据库的元数据(如表结构、索引等)。这种设计使得 SQLite3 对于需要将数据库存储在单一文件中的场景非常合适。

SQLite3 的数据库文件通常具有 .sqlite.db 扩展名,且它是 按页存储数据的。SQLite3 使用 1024 字节(默认)为基本存储单元,每个页面可以存储一个数据记录、索引节点、事务日志等。

当应用程序需要执行 SQL 查询时,它通过 SQLite3 的 API 来与数据库文件进行交互。SQLite3 会执行 SQL 语句,操作数据库文件,然后返回结果。

SQLite3 的优势

  1. 性能优越
    SQLite3 在单机应用中表现出色。由于 SQLite3 是直接对磁盘文件进行操作,并且没有复杂的数据库管理层,因此它的 I/O 性能相对较高,尤其在查询操作时速度较快。对于中小型数据集,SQLite3 几乎能够提供与传统数据库相媲美的性能。

  2. 高效的内存使用
    SQLite3 将数据直接存储到文件中,避免了传统数据库系统的内存消耗。在单个数据库连接上,SQLite3 能高效地使用内存,并且能在内存不足时通过分页操作优化性能。

  3. 简单易用
    SQLite3 的使用极为简单,不需要任何配置或启动额外的服务。只需要导入相应的 Go 包(如 github.com/mattn/go-sqlite3)即可与 SQLite3 交互。同时,它也支持完整的 SQL 语法,使得它对于熟悉 SQL 的开发人员来说非常直观。

  4. 事务支持和原子性
    SQLite3 支持完整的事务机制,它会自动进行事务的回滚,确保数据的一致性。在事务期间的所有操作都是原子的,要么全部成功,要么全部回滚,避免部分提交导致的数据不一致。

  5. 支持嵌入式环境
    由于 SQLite3 是嵌入式数据库,它非常适合在嵌入式设备、移动应用、桌面应用、物联网设备等资源有限的环境中使用。

SQLite3 的常见用途

  • 移动应用:SQLite3 是 Android 和 iOS 移动操作系统的默认数据库。它允许开发者在本地存储数据,无需依赖外部数据库服务。
  • 桌面应用:许多桌面应用程序(如浏览器、邮件客户端等)都使用 SQLite3 来存储用户数据和配置文件。
  • 嵌入式设备:SQLite3 被广泛用于嵌入式设备和物联网设备中,能够在有限的资源下提供数据库功能。
  • 数据存储:它也常常作为数据存储的解决方案,例如用于存储日志、历史记录、配置文件等。
  • 快速原型开发:SQLite3 适合快速原型开发和小型项目,开发者可以快速实现数据库功能,而不必担心数据库服务器的配置和维护。

SQLite3 与其他数据库的比较

特性 SQLite3 MySQL/PostgreSQL
安装与配置 零配置,直接使用数据库文件 需要安装和配置数据库服务
服务器需求 无需服务器,嵌入式数据库 需要独立的数据库服务器
性能 对小型数据集性能优越 大型数据集查询更高效
事务支持 完全支持 ACID 事务 完全支持 ACID 事务
扩展性 适合小到中型应用,单用户查询 支持高并发、多用户、大数据量
使用场景 本地存储、嵌入式、移动应用等 企业级应用、复杂查询等

总而言之,SQLite3 是一个轻量级的、无服务器的数据库系统,非常适合嵌入式应用、桌面应用和移动应用。它通过将数据库引擎嵌入到应用程序中,使得开发者能够快速实现数据存储功能,且不需要额外的数据库服务器或配置。对于小型到中型的数据存储需求,SQLite3 提供了高效、可靠的解决方案,同时也支持事务、ACID 原则等关系型数据库的重要特性。

SQLite 命令

如果你在sqlite3官网下载了一个sqlite引擎,那么就可以像python一样在cmd敲下一个sqlite3命令,然后在交互式命令行中使用sqlite3。(笔者没有下载)

在 sqlite3 中,SQL 语句需以分号 ; 结尾才会执行,允许跨行输入。特殊的点命令(如 .help 和 .tables)以小数点 . 开头,不需要分号结尾。

$ sqlite3
SQLite version 3.3.6
Enter ".help" for instructions
sqlite>

sqlite3的命令以.开头,如需获取可用的点命令的清单,可以输入 “.help”。例如:

sqlite>.help

上面的命令会显示各种重要的 SQLite 点命令的列表,如下所示:

命令 描述
.backup ?DB? FILE 备份 DB 数据库(默认是 "main")到 FILE 文件。
.bail ON|OFF 发生错误后停止。默认为 OFF。
.databases 列出数据库的名称及其所依附的文件。
.dump ?TABLE? 以 SQL 文本格式转储数据库。如果指定了 TABLE 表,则只转储匹配 LIKE 模式的 TABLE 表。
.echo ON|OFF 开启或关闭 echo 命令。
.exit 退出 SQLite 提示符。
.explain ON|OFF 开启或关闭适合于 EXPLAIN 的输出模式。如果没有带参数,则为 EXPLAIN on,即开启 EXPLAIN。
.header(s) ON|OFF 开启或关闭头部显示。
.help 显示消息。
.import FILE TABLE 导入来自 FILE 文件的数据到 TABLE 表中。
.indices ?TABLE? 显示所有索引的名称。如果指定了 TABLE 表,则只显示匹配 LIKE 模式的 TABLE 表的索引。
.load FILE ?ENTRY? 加载一个扩展库。
.log FILE|off 开启或关闭日志。FILE 文件可以是 stderr(标准错误)/stdout(标准输出)。
.mode MODE 设置输出模式,MODE 可以是下列之一:
  • csv 逗号分隔的值

  • column 左对齐的列

  • html HTML 的

    代码

  • insert TABLE 表的 SQL 插入(insert)语句

  • line 每行一个值

  • list 由 .separator 字符串分隔的值

  • tabs 由 Tab 分隔的值

  • tcl TCL 列表元素

  • .nullvalue STRING 在 NULL 值的地方输出 STRING 字符串。
    .output FILENAME 发送输出到 FILENAME 文件。
    .output stdout 发送输出到屏幕。
    .print STRING... 逐字地输出 STRING 字符串。
    .prompt MAIN CONTINUE 替换标准提示符。
    .quit 退出 SQLite 提示符。
    .read FILENAME 执行 FILENAME 文件中的 SQL。
    .schema ?TABLE? 显示 CREATE 语句。如果指定了 TABLE 表,则只显示匹配 LIKE 模式的 TABLE 表。
    .separator STRING 改变输出模式和 .import 所使用的分隔符。
    .show 显示各种设置的当前值。
    .stats ON|OFF 开启或关闭统计。
    .tables ?PATTERN? 列出匹配 LIKE 模式的表的名称。
    .timeout MS 尝试打开锁定的表 MS 毫秒。
    .width NUM NUM 为 "column" 模式设置列宽度。
    .timer ON|OFF 开启或关闭 CPU 定时器。

    使用 .show 命令,来查看 SQLite 命令提示符的默认设置。

    sqlite>.show
         echo: off
      explain: off
      headers: off
         mode: column
    nullvalue: ""
       output: stdout
    separator: "|"
        width:
    sqlite>
    

    可以使用下列的点命令来格式化输出为本教程下面所列出的格式:

    sqlite>.header on
    sqlite>.mode column
    sqlite>.timer on
    sqlite>
    

    上面设置将产生如下格式的输出:

    ID          NAME        AGE         ADDRESS     SALARY
    ----------  ----------  ----------  ----------  ----------
    1           Paul        32          California  20000.0
    2           Allen       25          Texas       15000.0
    3           Teddy       23          Norway      20000.0
    4           Mark        25          Rich-Mond   65000.0
    5           David       27          Texas       85000.0
    6           Kim         22          South-Hall  45000.0
    7           James       24          Houston     10000.0
    CPU Time: user 0.000000 sys 0.000000
    

    SQLite 语法

    SQLite 是不区分大小写的,但也有一些命令是大小写敏感的,比如 GLOB 和 glob 在 SQLite 的语句中有不同的含义。

    SQLite 注释是附加的注释,可以在 SQLite 代码中添加注释以增加其可读性,他们可以出现在任何空白处,包括在表达式内和其他 SQL 语句的中间,但它们不能嵌套。

    SQL 注释以两个连续的 “-” 字符(ASCII 0x2d)开始,并扩展至下一个换行符(ASCII 0x0a)或直到输入结束,以先到者为准。

    您也可以使用 C 风格的注释,以 “/" 开始,并扩展至下一个 "/” 字符对或直到输入结束,以先到者为准。SQLite的注释可以跨越多行。

    sqlite>.help -- 这是一个简单的注释
    

    所有的 SQLite 语句可以以任何关键字开始,如 SELECT、INSERT、UPDATE、DELETE、ALTER、DROP 等,所有的语句以分号 ; 结束,如:

    SQLite ANALYZE 语句:
    ANALYZE;
    or
    ANALYZE database_name;
    or
    ANALYZE database_name.table_name;
    
    SQLite AND/OR 子句:
    SELECT column1, column2....columnN
    FROM   table_name
    WHERE  CONDITION-1 {
      AND|OR} CONDITION-2;
    
    SQLite ALTER TABLE 语句:
    ALTER TABLE table_name ADD COLUMN column_def...;
    
    SQLite ALTER TABLE 语句(Rename):
    ALTER TABLE table_name RENAME TO new_table_name;
    
    SQLite ATTACH DATABASE 语句:
    ATTACH DATABASE 'DatabaseName' As 'Alias-Name';
    
    SQLite BEGIN TRANSACTION 语句:
    BEGIN;
    or
    BEGIN EXCLUSIVE TRANSACTION;
    
    SQLite BETWEEN 子句:
    SELECT column1, column2....columnN
    FROM   table_name
    WHERE  column_name BETWEEN val-1 AND val-2;
    
    SQLite COMMIT 语句:
    COMMIT;
    
    SQLite CREATE INDEX 语句:
    CREATE INDEX index_name
    ON table_name ( column_name COLLATE NOCASE );
    
    SQLite CREATE UNIQUE INDEX 语句:
    CREATE UNIQUE INDEX index_name
    ON table_name ( column1, column2,...columnN);
    
    SQLite CREATE TABLE 语句:
    CREATE TABLE table_name(
       column1 datatype,
       column2 datatype,
       column3 datatype,
       .....
       columnN datatype,
       PRIMARY KEY( one or more columns )
    );
    
    SQLite CREATE TRIGGER 语句:
    CREATE TRIGGER database_name.trigger_name 
    BEFORE INSERT ON table_name FOR EACH ROW
    BEGIN 
       stmt1; 
       stmt2;
       ....
    END;
    
    SQLite CREATE VIEW 语句:
    CREATE VIEW database_name.view_name  AS
    SELECT statement....;
    
    SQLite CREATE VIRTUAL TABLE 语句:
    CREATE VIRTUAL TABLE database_name.table_name USING weblog( access.log );
    or
    CREATE VIRTUAL TABLE database_name.table_name USING fts3( );
    
    SQLite COMMIT TRANSACTION 语句:
    COMMIT;
    
    SQLite COUNT 子句:
    SELECT COUNT(column_name)
    FROM   table_name
    WHERE  CONDITION;
    
    SQLite DELETE 语句:
    DELETE FROM table_name
    WHERE  {CONDITION};
    
    SQLite DETACH DATABASE 语句:
    DETACH DATABASE 'Alias-Name';
    
    SQLite DISTINCT 子句:
    SELECT DISTINCT column1, column2....columnN
    FROM   table_name;
    
    SQLite DROP INDEX 语句:
    DROP INDEX database_name.index_name;
    
    SQLite DROP TABLE 语句:
    DROP TABLE database_name.table_name;
    
    SQLite DROP VIEW 语句:
    DROP VIEW view_name;
    
    SQLite DROP TRIGGER 语句:
    DROP TRIGGER trigger_name
    
    SQLite EXISTS 子句:
    SELECT column1, column2....columnN
    FROM   table_name
    WHERE  column_name EXISTS (SELECT * FROM   table_name );
    
    SQLite EXPLAIN 语句:
    EXPLAIN INSERT statement...;
    or 
    EXPLAIN QUERY PLAN SELECT statement...;
    
    SQLite GLOB 子句:
    SELECT column1, column2....columnN
    FROM   table_name
    WHERE  column_name GLOB { PATTERN };
    
    SQLite GROUP BY 子句:
    SELECT SUM(column_name)
    FROM   table_name
    WHERE  CONDITION
    GROUP BY column_name;
    
    SQLite HAVING 子句:
    SELECT SUM(column_name)
    FROM   table_name
    WHERE  CONDITION
    GROUP BY column_name
    HAVING (arithematic function condition);
    
    SQLite INSERT INTO 语句:
    INSERT INTO table_name( column1, column2....columnN)
    VALUES ( value1, value2....valueN);
    
    SQLite IN 子句:
    SELECT column1, column2....columnN
    FROM   table_name
    WHERE  column_name IN (val-1, val-2,...val-N);
    
    SQLite Like 子句:
    SELECT column1, column2....columnN
    FROM   table_name
    WHERE  column_name LIKE { PATTERN };
    
    SQLite NOT IN 子句:
    SELECT column1, column2....columnN
    FROM   table_name
    WHERE  column_name NOT IN (val-1, val-2,...val-N);
    
    SQLite ORDER BY 子句:
    SELECT column1, column2....columnN
    FROM   table_name
    WHERE  CONDITION
    ORDER BY column_name {
      ASC|DESC};
    
    SQLite PRAGMA 语句:
    PRAGMA pragma_name;
    For example:
    PRAGMA page_size;
    PRAGMA cache_size = 1024;
    PRAGMA table_info(table_name);
    
    SQLite RELEASE SAVEPOINT 语句:
    RELEASE savepoint_name;
    
    SQLite REINDEX 语句:
    REINDEX collation_name;
    REINDEX database_name.index_name;
    REINDEX database_name.table_name;
    
    SQLite ROLLBACK 语句:
    ROLLBACK;
    or
    ROLLBACK TO SAVEPOINT savepoint_name;
    
    SQLite SAVEPOINT 语句:
    SAVEPOINT savepoint_name;
    
    SQLite SELECT 语句:
    SELECT column1, column2....columnN
    FROM   table_name;
    
    SQLite UPDATE 语句:
    UPDATE table_name
    SET column1 = value1, column2 = value2....columnN=valueN
    [ WHERE  CONDITION ];
    
    SQLite VACUUM 语句:
    VACUUM;
    
    SQLite WHERE 子句:
    SELECT column1, column2.

    你可能感兴趣的:(golang,golang,sqlite,jvm)