0

我有一个看起来像这样的查询:

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使用索引进行速度优化的同时达到上述查询的效果呢?

4

1 回答 1

1

有了这么多 OR 连接的术语,有效地使用索引是不可能的

您绝对应该使用动态查询字符串。如果您认为准备这些需要太长时间,请构建一个准备好的语句缓存,以查询字符串为键。(准备好的语句使用很少的内存。)

于 2014-03-12T17:10:47.900 回答