次のようなクエリがあります。
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
残りの列フィルターが NULL である限り、WHERE セクションの任意の列でフィルター処理できるようにしたいので、クエリはこれほどばかげているように見えます。たとえば、残りのキーが に設定されている限り、同じ準備済みステートメントに{street_name: "foo", house_number: 12}
またはを渡すことにより、上記のクエリを使用してアドレスを検索できます。{postal_code: 1234, house_number: 5}
nil
このクエリの問題は、SQLite3 が明らかにデータベース インデックスの使用に失敗していることです。このクエリは、1 秒あたり 6 ~ 8 回しか実行されません。WHERE
セクションを次のように置き換えてWHERE sa.house_number = ? AND sn.name = ?
クエリを準備すると、1 秒あたり 110,000 回以上実行されます。
クエリを実行するたびにクエリを動的に作成することもできますが、検索ごとにそれだけ多くの作業を導入し、さらに準備済みステートメントを使用する機能を失うと、クエリの速度が 1 秒あたり約 4000 回の実行に低下します。
概要:
速度の最適化のためにインデックスを使用するように SQLite3 を納得させながら、上記のクエリの効果を達成する方法はありますか?