我有一个看起来像这样的查询:
SELECT
sn.name, -- Street name
sa.house_number, -- House number
sa.entrance, -- Entrance
pc.postal_code, -- Postal code
ci.name, -- City
mu.name, -- Municipality
co.name -- County
FROM
street_addresses AS sa
INNER JOIN street_names AS sn ON sa.street_name = sn.id
INNER JOIN postal_codes AS pc ON sa.postal_code = pc.id
INNER JOIN cities AS ci ON sa.city = ci.id
INNER JOIN municipalities AS mu ON sa.municipality = mu.id
INNER JOIN counties AS co ON mu.county = co.id
WHERE
(:id IS NULL OR sa.id = :id) AND
(:street_name IS NULL OR sn.name = :street_name) AND
(:house_number IS NULL OR sa.house_number = :house_number) AND
(:entrance IS NULL OR sa.entrance = :entrance) AND
(:postal_code IS NULL OR pc.postal_code = :postal_code) AND
(:city IS NULL OR ci.name = :city) AND
(:municipality IS NULL OR mu.name = :municipality) AND
(:county IS NULL OR co.name = :county)
ORDER BY
sn.name ASC, sa.house_number ASC, sa.entrance ASC
该查询看起来很愚蠢,因为我希望能够按 WHERE 部分中的任何列进行过滤,只要其余列过滤器为 NULL。例如,只要将其余键设置{street_name: "foo", house_number: 12}
为.{postal_code: 1234, house_number: 5}
nil
这个查询的问题是 SQLite3 显然无法使用数据库索引。此查询每秒仅运行 6 到 8 次。如果我替换该WHERE
部分WHERE sa.house_number = ? AND sn.name = ?
并准备查询,它每秒运行超过 110 000 次。
我可以在每次运行时动态构建查询,但是为每次搜索引入大量工作,加上失去使用准备好的语句的能力,将查询速度降低到每秒约 4000 次运行。
概括:
有没有什么办法可以在说服SQLite3使用索引进行速度优化的同时达到上述查询的效果呢?