python - 参数替换后让sqlite3进行查询优化
问题描述
我只是将性能问题追溯到 sqlite3 中的查询优化(我正在使用 Python 接口,但我不确定它是否相关,问题可能与 sqlite API 有关)。
我在下面描述了这样一个例子。
我的表看起来像这样,有数百万条记录:
CREATE TABLE articles (
id integer primary key,
title text,
)
CREATE TABLE "tags" (
tag text,
article_id integer not null,
foreign key(article_id) references articles(id),
)
这是我要运行的请求:
SELECT tag
FROM "tags" AS t1
INNER JOIN
(
SELECT id
FROM "articles"
LIMIT (?)
) t2
ON t1.article_id = t2.id
我观察到,如果限制参数是硬编码的,那么查询会更快(0.01s vs 15s)。
使用set_trace_callback
,我看到查询完全一样。
但是,explain
没有给出相同的结果。
我得出的结论是 SQLite 查询优化器在参数替换之前运行。
确实,如果我将查询修改为
SELECT t1.tag FROM
(
SELECT id
FROM "articles"
LIMIT (?)
) as t2 CROSS JOIN
"tags" as t1
WHERE
t1.article_id = t2.id
它的工作速度与硬编码限制相同,因为 CROSS JOIN 允许控制 for 循环(链接)的顺序。
因此,我得出结论,查询优化器不会以相同的顺序运行嵌套循环。
在这个玩具示例中,有一个明显更好的顺序。但是,在其他情况下,我可能希望查询优化器在参数替换后运行。
有没有办法在仍然使用防止 SQL 注入的安全方法的同时做到这一点?
简单的解决方案是验证限制是整数并使用简单的字符串替换。
解决方案
推荐阅读
- npm - 如何使用带有 Sass 和 RTL 支持的 Bootstrap?
- python - pathlib 绝对路径与配置解析器行为异常
- api - 如何将json-data放入flutter列表中?
- postgresql - 为什么主键上的“order by”会更改查询计划,从而忽略有用的索引?
- sonos - Sonos Control Api:获取sonos账户信息
- graphql - 数组查询中的GraphQL“全部”?
- android - 为什么我的 CameraX CameraView 显示黑屏?
- ruby-on-rails - RSpec:断言成功的创建请求没有分配方法
- firebase - 仅当用户知道节点时才授权写入和删除 - 规则 Firebase
- rundeck - 有什么方法可以禁用 rundeck 中的排名顺序吗?