Last active
April 6, 2025 02:16
-
-
Save alexcwatt/025e1c0ce92288e0d12190e299c48075 to your computer and use it in GitHub Desktop.
Ruby SQLite query plan regression
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| *.sqlite |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 3.4.1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require "bundler/inline" | |
| sqlite_version = if ENV["REGRESSION"] | |
| "2.0.0" # vendored sqlite: 3.45.3 | |
| else | |
| "1.7.3" # vendored sqlite: 3.45.2 | |
| end | |
| gemfile do | |
| source "https://rubygems.org" | |
| gem "benchmark" | |
| gem "sqlite3", "~> #{sqlite_version}" | |
| end | |
| require "sqlite3" | |
| puts "Using sqlite3 version: #{SQLite3::VERSION}" | |
| file_path = "repro.sqlite" | |
| File.delete(file_path) if File.exist?(file_path) | |
| db = SQLite3::Database.new(file_path) | |
| db.execute_batch(File.read("repro.sql")) | |
| query = "SELECT * FROM products WHERE processed = 0 AND _enqueued = 0 LIMIT 1;" | |
| puts "=== EXPLAIN QUERY PLAN ===" | |
| puts db.execute("EXPLAIN QUERY PLAN #{query}") | |
| puts "=== BENCHMARK QUERY (single run) ===" | |
| puts Benchmark.measure { db.execute(query) } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| begin deferred transaction; | |
| CREATE TABLE products ( | |
| `id` INTEGER PRIMARY KEY, | |
| `errors` TEXT, | |
| `processed` INTEGER DEFAULT 0, | |
| `_enqueued` INTEGER DEFAULT 0, | |
| `title` TEXT | |
| ); | |
| WITH RECURSIVE product_numbers(n) AS ( | |
| SELECT 1 | |
| UNION ALL | |
| SELECT n + 1 FROM product_numbers WHERE n < 1000000 | |
| ) | |
| INSERT INTO products (`title`) SELECT 'Product ' || n FROM product_numbers; | |
| commit transaction; | |
| CREATE INDEX IF NOT EXISTS products_to_import_idx ON products (`_enqueued`) WHERE processed = 0; | |
| CREATE INDEX IF NOT EXISTS products_progress_idx ON products (`processed`, `errors`); | |
| PRAGMA optimize=0x10002; | |
| UPDATE products SET processed=1 WHERE id <= 900000; | |
| EXPLAIN QUERY PLAN SELECT * FROM products WHERE processed = 0 AND _enqueued = 0 LIMIT 1; |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Results of the script on my MacBook Pro.
sqlite3-ruby 1.7.3 (vendored sqlite: 3.45.2)
sqlite3-ruby 2.0.0 (vendored sqlite: 3.45.3)