检测 SQLite 中的全表扫描

Lobsters Hottest 工具

摘要

本文展示了如何利用 SQLite 的语句统计 API 检测全表扫描,并建议将其集成到 Rails 中,以便在测试/开发环境中发出警告或报错。

<p><a href="https://lobste.rs/s/eilycs/detecting_full_table_scans_with_sqlite">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/07/16 01:50

# 使用 SQLite 检测全表扫描 来源:https://tenderlovemaking.com/2026/07/15/detecting-full-table-scans-with-sqlite/ 本周我正在参加 RubyConf(https://rubyconf.org/),感觉太棒了! 我最近读到 lobste.rs(https://lobste.rs/)现在运行在 SQLite 上(https://lobste.rs/s/ko1ji1/lobste_rs_is_now_running_on_sqlite)。文章中有一部分引起了我的注意: > 我希望我们能在测试中说:“如果遇到任何全表扫描就失败。” 这样本可以帮我们抓住第一次部署时遇到的性能问题。 SQLite 会收集预编译语句的信息,并通过 API(https://sqlite.org/c3ref/stmt_status.html)暴露这些统计数据。这意味着我们在执行语句后,无需使用 `EXPLAIN` 就能判断该语句是否进行了全表扫描。 下面是一个示例程序,演示如何检测查询是否进行了全表扫描: ```ruby db = SQLite3::Database.new(":memory:") db.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)") # 插入大量记录 1_000.times do |i| db.execute("INSERT INTO users (name, age) VALUES (?, ?)", ["user#{i}", i % 100]) end # 准备一个语句并查询 stmt = db.prepare("SELECT * FROM users WHERE age = ?") stmt.bind_param(1, 42) stmt.to_a # 检查全扫描步数,由于查询进行了全表扫描,我们会看到很多步 fullscan_steps = stmt.stat(:fullscan_steps) puts "fullscan_steps: #{fullscan_steps}" if fullscan_steps > 0 puts "=> 查询进行了全表扫描" end # 创建索引 db.execute("CREATE INDEX idx_users_age ON users(age)") # 现在查询不再进行全表扫描 stmt2 = db.prepare("SELECT * FROM users WHERE age = ?") stmt2.bind_param(1, 42) stmt2.to_a puts "添加索引后,fullscan_steps: #{stmt2.stat(:fullscan_steps)}" ``` 感觉我们可以将其集成到 Rails 中,在测试或开发模式下发出警告或直接异常。我不确定是否要在生产环境中始终检查这一点,但也许也没问题?

相似文章

用细齿梳检查 SQLite

Lobsters Hottest

John Regehr 描述了使用 tis-interpreter 在 SQLite 中搜索未定义行为,发现了其他工具遗漏的错误,如悬空指针使用和未初始化读取。

在SQLite中推荐使用严格表

Hacker News Top

SQLite的严格表强制执行严格类型检查,以防止常见的数据类型错误。本文介绍了如何使用它们以及它们的优缺点。

我用于检测交易欺诈的SQL模式

Hacker News Top

一份实用指南,介绍六种用于检测金融数据中交易欺诈的SQL模式,包括速度检查、不可能旅行检测等方法。作者分享了真实案例和调优建议。

SQLite 查询解释器

Simon Willison's Blog

一个基于浏览器的工具,可对 SQLite 运行 SQL 查询,并以通俗易懂的英文解释查询计划和字节码输出。