私は、ユーザーが一連のファクト テーブルに対して任意にクエリを実行できるようにするレポート システムに取り組んでおり、ファクト テーブルごとに複数のディメンション テーブルを制限しています。制約パラメーターに基づいてすべての正しい結合とサブクエリを自動的にアセンブルするクエリ ビルダー クラスを作成しましたが、すべてが設計どおりに機能します。
しかし、私は最も効率的なクエリを生成していないと感じています。数百万件のレコードを含む一連のテーブルでは、これらのクエリの実行に約 10 秒かかります。1 秒未満の範囲に収まるようにしたいと考えています。サブクエリを取り除くことができれば、結果ははるかに効率的になると感じています。
実際のスキーマ (はるかに複雑です) を示すのではなく、アプリケーションとデータ モデル全体を説明することなく、要点を説明する類似の例を示します。
アーティストと会場を含むコンサート情報のデータベースがあるとします。ユーザーは、アーティストと会場を任意にタグ付けできます。したがって、スキーマは次のようになります。
concert
id
artist_id
venue_id
date
artist
id
name
venue
id
name
tag
id
name
artist_tag
artist_id
tag_id
venue_tag
venue_id
tag_id
ものすごく単純。
ここで、今日から 1 か月以内に開催されるすべてのコンサート、「cheap-beer」および「great-mosh-pits」タグでコンサートに出演する「テクノ」および「トロンボーン」タグを持つすべてのアーティストについて、データベースにクエリを実行するとします。 .
私が思いついた最高のクエリは次のようになります。
SELECT
concert.id AS concert_id,
concert.date AS concert_date,
artist.id AS artist_id,
artist.name AS artist_name,
venue.id AS venue_id,
venue.name AS venue_name,
FROM
concert
INNER JOIN (
artist ON artist.id = concert.artist_id
) INNER JOIN (
venue ON venue.id = concert.venue_id
)
WHERE (
artist.id IN (
SELECT artist_id
FROM artist_tag
INNER JOIN tag AS a on (
a.id = artist_tag.tag_id
AND
a.name = 'techno'
) INNER JOIN tag AS b on (
b.id = artist_tag.tag_id
AND
b.name = 'trombone'
)
)
AND
venue.id IN (
SELECT venue_id
FROM venue_tag
INNER JOIN tag AS a on (
a.id = venue_tag.tag_id
AND
a.name = 'cheap-beer'
) INNER JOIN tag AS b on (
b.id = venue_tag.tag_id
AND
b.name = 'great-mosh-pits'
)
)
AND
concert.date BETWEEN NOW() AND (NOW() + INTERVAL 1 MONTH)
)
クエリは機能しますが、これらの複数のサブクエリを使用するのは本当に好きではありません。純粋に JOIN ロジックを使用して同じロジックを実現できれば、パフォーマンスが大幅に向上すると感じています。
完璧な世界では、実際の OLAP サーバーを使用することになります。しかし、私の顧客は MySQL、MSSQL、または Postgres にデプロイする予定であり、互換性のある OLAP エンジンが利用できるとは保証できません。そのため、スター スキーマを持つ通常の RDBMS を使用することに行き詰まっています。
この例の詳細にあまりこだわらないでください (私の実際のアプリケーションは音楽とは何の関係もありませんが、ここで示したものと類似した関係を持つ複数のファクト テーブルがあります)。このモデルでは、「artist_tag」テーブルと「venue_tag」テーブルがファクト テーブルとして機能し、それ以外はすべてディメンションです。
この例では、ユーザーが単一の artist_tag またはvenue_tag 値に対してのみ制約できるようにすると、クエリの記述がはるかに簡単になることに注意することが重要です。複数の異なるタグを必要とする AND ロジックをクエリに含めることを許可する場合にのみ、非常に扱いにくくなります。
私の質問は、複数のファクト テーブルに対して効率的なクエリを作成するための、あなたが知っている最良の手法は何ですか?