0

同一の列を持つ 2 つのテーブルを結合し、その結果を複雑な JOIN クエリで使用する必要がありますが、パフォーマンスが大幅に低下します。UNION を使用したこのクエリの実行時間は 7 秒です。

SELECT DISTINCT `admin`.`Fund_ID`,
                `admin`.`Fund_Name`
FROM (
        (SELECT *
         FROM `admin`)
      UNION
        (SELECT *
         FROM `admin_custom`
         WHERE `user_id`=361)) admin
LEFT JOIN (
             (SELECT *
              FROM `quant1`)
           UNION
             (SELECT *
              FROM `quant1_cust`
              WHERE `user_id`=361)) quant1 
ON (quant1.`Fund ID`=`admin`.`Fund_ID`)
WHERE quant1.`VaR 95`>-0.028

ただし、UNION 句を単純なテーブルに置き換えると、わずか 0.006 秒になります。パフォーマンスの問題を修正するにはどうすればよいですか?

4

2 に答える 2

0

これには当て推量が含まadminquant1ます。そしてadmin_customただquant1_cust?これにより、これら 2 つのフィールドの個別のリストに必要な労力が軽減されます。

SELECT `Fund_ID`, `Fund_Name`
FROM `admin`
INNER JOIN `quant1` ON `admin`.`Fund_ID` = `quant1`.`Fund_ID`
                   AND `quant1`.`VaR 95`>-0.028

UNION

SELECT `Fund_ID`, `Fund_Name`
FROM `admin_custom`
INNER JOIN `quant1_cust` ON `admin_custom`.`Fund_ID` = `quant1_cust`.`Fund_ID`
                        AND `admin_custom`.`user_id` = `quant1_cust`.`user_id`
                        AND `quant1_cust`.`VaR 95`>-0.028
WHERE `admin_custom`.`user_id`=361
;

既存のクエリ構造を見ると、しないことをお勧めすることがいくつかあります。UNION と SELECT DISTINCT を使用しても意味がありません。select * を UNION または UNION ALL と一緒に使用しないでください。具体的にして、本当に必要なフィールドのみを含めてください。また、既存の where 句は、左結合によって返される null を抑制します。そのため、左結合を使用しないでください。

SELECT DISTINCT --<< effort for distinctiveness here
...
FROM (
      SELECT * --<< too many fields
      ...
      UNION --<< effort for distinctiveness here

      SELECT * --<< too many fields
      ...
     )
LEFT JOIN (
            SELECT * --<< too many fields
            ...
            UNION --<< effort for distinctiveness here

            SELECT * --<< too many fields
            ...
           ) quant1
WHERE quant1 ...

編集: 代替 - 申し訳ありませんが、この方法に従う方が簡単かもしれません:

SELECT `Fund_ID`, `Fund_Name`
FROM `admin`
INNER JOIN `quant1` ON `admin`.`Fund_ID` = `quant1`.`Fund_ID`
WHERE `quant1`.`VaR 95`>-0.028

UNION

SELECT `Fund_ID`, `Fund_Name`
FROM `admin_custom`
INNER JOIN `quant1_cust` ON `admin_custom`.`Fund_ID` = `quant1_cust`.`Fund_ID`
                        AND `admin_custom`.`user_id` = `quant1_cust`.`user_id`
WHERE `admin_custom`.`user_id`=361
AND `quant1_cust`.`VaR 95`>-0.028
;
于 2013-10-09T07:57:14.327 に答える
0

UNIONED テーブル間の共通性を作成するために、データベースに「追加の変更」を行うことができます。これは、テーブルと列を追加するだけのリファクタリングであり、変更されていないアプリケーション コードとの読み取り互換性を維持します。

この例では、「の左側」に共通テーブルを作成し、adminそこadmin_customから結合します。これには、Fund ID、TYPE (参加しているのがわかります)、および可能であればその他の有用な共通列が含まれます。

また、「の左側」に共通テーブルを作成し、quant1そこquant1_custから結合ます。

次に、共通テーブルから Fund-ID リンケージを使用するようにクエリを変更し、UNION 句を「共通テーブル」のみ (可能であれば) または"Common Table" left outer join Legacy1 left outer join Legacy2.

これらのテーブルが実際に「何であるか」を理解していないので、賢明な命名についてはお手伝いできません. (ネーミングは設計の最も重要な部分であり、質問でこれを説明する必要がありました。)

しかし、このアプローチは、私が主導した主要な政府プロジェクトで非常にうまく機能しました。共通テーブルは DOCUMENT と DOC_ELEMENT でした。8 つの異なるドキュメント タイプを持ち、既存の共通性がないツリー構造のドキュメント。

私たちの場合、DOCUMENT は RFP、TENDER、PRICEPLAN などの「左側」に追加され、共通性が提供されました。

完全な下位互換性ではありません。アプリケーションの INSERT コードを変更する必要があります。また、リファクタリングを開始する場合は、同じテーブル構造を同じテーブルに配置することを検討してください。

最善の方法は、可能な構造を試し、可能なパフォーマンスを検証し、必要なコードの変更を計画することです。その後、軌道を選択できます。

于 2013-10-09T05:03:43.410 に答える