0

次のテーブル構造を使用します。

表 1:顧客

CustID(primary key)  |  CustName(indexed)
----------------------------------
C1                       Cust1
C2                       Cust2
.                        Cust3
.                        Cust.
.                        Cust.
C10000                   Cust10000

表 2:カスタムフィールド

FieldID (primary key) |  ID (indexed)                | FieldValue
---------------------------------------------------------------------
1                        C1                              Test 
2                        C2                              Test 
3                        C3                              Test 
4                        C4                              Test 
.                        .                               Test 
.                        .                               Test 
few millions             Z1                              Test   

"ID" column is indexed.

以下を出力しようとしています。

CustID  |  Field 1  |  Field 2 | Field 3 | .... | Field N
----------------------------------------------------------

のようなクエリを書いてみました

Select 
    CustID, A1.FieldValue as [Field 1], A2.FieldValue as [Field 2]
from 
    Customers 
left outer join 
    CustomFields A1 on Customers.custID = A1.ID
left outer join 
    CustomFields A2 on Customers.custID = A2.ID
left outer join 
    CustomFields An on Customers.custID = An.ID
where 
    custName like 'C%'

テーブルには数百万のレコードが含まれているためCustomFields、上記のクエリはうまく機能しません。現在、約 10 ~ 12 秒かかります (500 人の顧客と 6 つのフィールドの場合)。

ここで左外部結合が時間を追加していると思います。問題を解決するための考えは本当に役に立ちますか?

プラットフォーム: SQL Server 2005

更新しました :

CustomFieldstable は一般的なテーブルであり、他のエンティティ (ベンダー、アイテムなど) のフィールドを含めることができます。

4

4 に答える 4

1

Database Engine Tuning Advisorを使用してクエリを分析してみましたか?保証はありませんが、役立つ提案が1つか2つ提供される場合があります。

ここに画像の説明を入力してください

于 2012-05-22T16:33:59.463 に答える
0

単一の結合を使用してカスタムフィールドを取得し、集計関数を使用してそれらを転置することができます。このように、テーブルCustomFieldsとの結合は1回だけ実行されます。

このような。

SELECT
  Customers.CustID,
  MAX(CASE WHEN CF.FieldID = 1 THEN CF.FieldValue ELSE NULL END) AS Field1,
  MAX(CASE WHEN CF.FieldID = 2 THEN CF.FieldValue ELSE NULL END) AS Field2,
  MAX(CASE WHEN CF.FieldID = 3 THEN CF.FieldValue ELSE NULL END) AS Field3,
  MAX(CASE WHEN CF.FieldID = 4 THEN CF.FieldValue ELSE NULL END) AS Field4
  -- Add more...

  FROM Customers 

  LEFT OUTER JOIN CustomFields CF
  ON CF.ID = Customers.CustID

  WHERE Customers.CustName like 'C%'

  GROUP BY Customers.CustID
于 2012-05-24T12:49:29.940 に答える
0
    SELECT  Pvt.ID, 
            Customers.CustName, 
            Pvt.[1] AS Field1, 
            Pvt.[2] AS Field2, 
            Pvt.[3] AS Field3, 
            Pvt.[4] AS Field4, 
            Pvt.[5] AS Field5,
            ...
    FROM (
            SELECT ID, FieldID, FieldValue
            FROM CustomFields) AS p
            PIVOT (
                MIN (FieldValue)
                FOR FieldID IN ([1], [2], [3], [4], [5], ... )
        ) AS pvt
    inner join Customers ON Customers.CustID = pvt.ID
于 2012-05-23T06:21:00.990 に答える
0

クエリは完全に合理的です。ただし、データベース構造はオフです。顧客 ID 用とフィールド ID 用に別の列が必要です。クエリの記述方法により、CustId の行を他のテーブルのフィールドと同じ数だけ取得できます。

それらを 1 つの列に結合しないでください。結合は次のようになると思います。

left outer join
CustomerFields cfn
on cfn.CustId = Customers.CustId and
   cfn.FieldNum = <n>

もう 1 つの可能性は、クエリを初めて実行したときにパフォーマンス ヒットが発生したことです。十分なメモリがあれば、フィールド テーブルがメモリ内にあるため、2 回目ははるかに高速に実行される可能性があります。

記録のために、私は「好き」に対して歴史的な偏見を持っています。それがパフォーマンスの問題を引き起こすと信じています。これは役に立たないかもしれませんが、試すことができます:

where left(CustName, 1) = 'C'
于 2012-05-22T14:57:52.503 に答える