把真机那道题在纸上预演一遍

👁️ 0 人浏览 💬 0 人评论 ❤️ 添加收藏

真机交付题的形状:给一条走 SCAN 的查询建索引,量出前后碰的行数输出两个数(用 / 隔开)。

t 表:200 行
id    1 ~ 200,主键
cat   只有 "A" 和 "B" 两种值(奇数行 A、偶数行 B)
v     i * 3 % 500,取值范围 0 ~ 499
note  "n1" ~ "n200"

两个现成的工具函数(题面里已经写好)
plan(sql)     → 打出 SCAN(扫全表)还是 SEARCH(顺着索引找)
counted(sql)  → 数出这条查询把条件判了多少次(条件里要放 tick())
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, cat TEXT NOT NULL, "
           "v INTEGER NOT NULL, note TEXT NOT NULL)")
db.executemany("INSERT INTO t VALUES (?,?,?,?)",
               [(i, "A" if i % 2 else "B", i * 3 % 500, "n" + str(i))
                for i in range(1, 201)])
db.commit()

def plan(sql):
    """看数据库打算怎么取数:SCAN=扫全表,SEARCH=顺着索引找。"""
    return db.execute("EXPLAIN QUERY PLAN " + sql).fetchall()[0][3]

def counted(sql):
    """数一数这条查询把条件判了多少次(= 扫了多少行)。
    ⚠️ tick() 必须写在条件的**最前面**:写在后面时它只对已经匹配上的行求值,
       数出来的就变成"结果有几行",而不是"扫了几行"。"""
    hits = {"n": 0}
    db.create_function("tick", 0, lambda: hits.__setitem__("n", hits["n"] + 1) or 1)
    db.execute(sql).fetchall()
    return hits["n"]
a = counted("SELECT * FROM t WHERE tick() AND note = 'n99'")
db.execute("CREATE INDEX ix_note ON t(note)")
b = counted("SELECT * FROM t WHERE tick() AND note = 'n99'")
print(str(a) + "/" + str(b))
提交你的答案
请登录后提交答案。
去登录
代码编辑器
Ctrl + Enter 运行
本次输入:
输出:

                        
👩‍🏫
AI
💬 题目评论

全部评论