5

PHP プロジェクトにフィルター関数を実装したいと考えています。フィルターを実装するには、通常、クエリに WHERE 句を追加して、フィルター処理された結果を表示します。

私の問題は次のとおりです。これらのフィルターには、追加された単純な WHERE 句だけでなく、複数の JOIN を含む巨大なクエリが必要です。結果のクエリには 30 行以上あります。

後で、この巨大なクエリも必要とする検索機能も必要です。これが良い方法なのか、それとも更新ごとにフィルタリングするために必要な属性を計算するデータベース テーブルに「冗長な」データベース列を追加する必要があるのか​​ 疑問に思います。この列を使用すると、プロジェクトのさまざまな場所で巨大なクエリを実行することはできなくなりますが、冗長な列ができます。

どう思いますか?

ご挨拶

質問されたように、ここにテーブル構造/コードがあります。これは正確なコードではありません。これは、さらに複雑にするリビジョン システムも存在するためですが、理解するにはこれで十分です。

テーブル提出:

ID (primary)
(additionalColumns)

テーブル レポート:

ID (primary)
submissionID (reference to submission table)
(additionalColumns)

テーブル report_objects:

reportID (reference to reports table, multiple report_object for one report)

テーブル アカウンティング:

ID (primary)
reportID (reference to reports table, multiple accountings for one report)
(additionalColumns)

テーブル account_objects:

ID
accountingID (reference to accounting table, multiple accounting_object for one accounting)
(additionalColumns)

送信の場合、複数のオブジェクト (report_objects) を考慮して 1 つまたは複数のレポートが作成されます。レポートごとに、複数のアカウンティングを作成できます。各アカウンティングは、レポートのいくつかのオブジェクト用です。アカウンティングされた report_objects は、accounting_object に格納されます

私のクエリ/フィルターは、submissionID の各 report_object が 1 つの submitID に対してアカウント化されている (accounting_object が存在する) かどうかをチェックします。

4

1 に答える 1

4

決定的な答えは1つではありません。実際には、それが機能し、ニーズに十分な速さで実行される場合は、そのままにしておくことができます。最適化は常にあなたが戻ることができるものです。

正しく参加する

単に結合テーブルの存在をチェックし、その結合の結果のみを含める場合は、正しいLEFT /RIGHTJOIN式を使用してこれを行うことができます。これは常に最初の呼び出しです。

表現力

また、SQLでできる限り表現力を発揮し、クエリを最適化するための最良の機会を与えたいと考えています。たとえば、EXISTSなどのキーワードがあります。必ずそれらを使用してください。

非正規化

計算された値を格納する列に追加できます。これから生じる複雑さは、値が常に最新であることを保証します。これは、トリガーまたは手動で実行できます。長所:

  • これは、計算列によってもたらされる速度低下を回避するための最も簡単な方法です。

短所:

  • 正規化されたスキーマを台無しにする
  • コードで手動で行うと、どこかで行うのを忘れてしまい、頭痛の種になります。
  • トリガーは少し苦痛になる可能性があります。

マテリアライズドビュー

これは非正規化に似ていますが、保存されたビューを作成することで正規化されたテーブルを汚染することを防ぎます。これは、MySQLで、値が変更されたときに複雑な選択の結果を結果テーブルに格納することで実現されます。繰り返しますが、非正規化と同じように、複雑さはこれを最新の状態に保ちます。これは通常、トリガーを使用して行われます。これは苦痛かもしれませんが、スキーマの複雑さを防ぎます。@ egyalが述べたように、これはまだMySQLでサポートされている機能ではないため、DIYする必要があります... MySQLを使用したマテリアライズドビュー

長所:

  • ダーティな非正規化されたものを、適切な正規化されたスキーマから遠ざけます。

短所:

  • マテリアライズド・ビューはサポートされていないため、セットアップには作業が必要です。
  • コードでビューの更新をトリガーすると、古いデータが取得されますが、非正規化の単一列の古さほど苦痛ではありません。
  • トリガーは少し苦痛になる可能性があります。

よくわからない場合、そしてそれが本当に重要な場合は、ベンチマークを実行してください。

編集コードベース全体でこのクエリが何らかの形でコードに含まれている場合、ステートメントが変更された場合、または変更されたときにすべての場所でステートメントを変更することを忘れないようにする必要があるため、将来的に頭痛の種になる可能性があります。

上記を実行することにより、ステートメントを非常に単純で簡潔にした場合、問題にならないように、それらは互いに十分に異なる可能性があります。

あなたはあなたを助けるためにいくつかのことをすることができます:

  1. 関連するすべてのクエリを1つの場所に配置します。つまり、このクエリをさまざまな形式で処理する単一のクラスまたはスクリプトです。このように、少なくともすべての変更は1つのファイルに制限されます。
  2. もう少し自分自身を助けるために、クエリ間の重複を取り除くためにそれを少しリファクタリングすることができます。

また、データベース情報がコードに公開されすぎていると感じた場合は、ビューの背後でそれを抽象化することをお勧めします。

于 2012-12-14T10:21:02.113 に答える