0
SELECT BB.NAME BranchName,VI.NAME Village,COUNT(BAC.CBSACCOUNTNUMBER) "No.Of Accounts",
SUM(BAC.CURRENTBALANCE) SumOfAmount,
SUM(CASE WHEN transactiontype = 'C' THEN amount ELSE 0 END) AS CreditTotal,
SUM(CASE WHEN transactiontype = 'D' THEN amount ELSE 0 END) AS DebitTotal,
SUM(CASE WHEN transactiontype = 'C' THEN amount WHEN transactiontype = 'D' THEN -1 * amount ELSE 0 END) AS CurrentBalance
FROM CUSTOMER CU,APPLICANT AP,ADDRESS AD,VILLAGE VI,BANKBRANCH BB,BANKACCOUNT BAC
LEFT OUTER JOIN accounttransaction ACT ON ACT.BANKACCOUNT_CBSACCOUNTNUMBER=BAC.CBSACCOUNTNUMBER
AND DATE_FORMAT(ACT.TRANDATE,'%Y-%m-%d')<='2013-05-09'
AND DATE_FORMAT(BAC.ACCOUNTOPENINGDATE,'%Y-%m-%d') <'2013-05-09'
AND ACT.BANKACCOUNT_CBSACCOUNTNUMBER IS NOT NULL
WHERE CU.CODE=AP.CUSTOMER_CODE AND BAC.ENTITY='CUSTOMER' AND BAC.ENTITYCODE=CU.CODE
AND AD.ENTITY='APPLICANT' AND AD.ENTITYCODE=AP.CODE
AND AD.VILLAGE_CODE=VI.CODE AND VI.STATE_CODE=AD.STATE_CODE AND VI.DISTRICT_CODE=AD.DISTRICT_CODE
AND VI.BLOCK_CODE=AD.BLOCK_CODE AND VI.PANCHAYAT_CODE=AD.PANCHAYAT_CODE
AND CU.BANKBRANCH_CODE=BB.CODE AND BAC.CBSACCOUNTNUMBER IS NOT NULL AND ACT.TRANSACTIONTYPE IS NOT NULL
GROUP BY BB.NAME,VI.NAME LIMIT 10;

and 

below is my explain plan

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  AD  index   ADDRESS_ENTITYCODE  ADDRESS_ENTITYCODE  598 NULL    47234   Using where; Using index; Using temporary; Using filesort
1   SIMPLE  VI  ref PRIMARY PRIMARY 62  fiserveraupgb.AD.VILLAGE_CODE   1   Using where
1   SIMPLE  AP  eq_ref  PRIMARY,AppCodeIndex    PRIMARY 62  fiserveraupgb.AD.ENTITYCODE 1   
1   SIMPLE  BAC ref BANKACCOUNT_ENTITYCODE  BANKACCOUNT_ENTITYCODE  63  fiserveraupgb.AP.CUSTOMER_CODE  1   Using where; Using index
1   SIMPLE  CU  eq_ref  PRIMARY,CustCodeIndex   PRIMARY 62  fiserveraupgb.AP.CUSTOMER_CODE  1   
1   SIMPLE  BB  ref PRIMARY,Bankbranch_CodeName PRIMARY 62  fiserveraupgb.CU.BANKBRANCH_CODE    1   
1   SIMPLE  ACT index   NULL    accounttransaction_sysidindes   280 NULL    22981   Using where; Using index; Using join buffer

Mysqlサーバーバージョン5.5で、以下のmysqlワークベンチを使用しています。実行に13分かかるクエリです。関連するすべての列のインデックスを作成した最適な方法を提案してください。

4

1 に答える 1

1

主に、結合と where 句で使用される列にインデックスが必要です。他のインデックスは、選択ステートメントに価値を追加せず、挿入と更新を遅くします。

この場合、関数で列の値を使用しています。このため、インデックスを効率的に使用できません。

次のような式は非常に非効率的です。

DATE_FORMAT(ACT.TRANDATE,'%Y-%m-%d')<='2013-05-09'

すべての TRANDATES がその値の文字列表現に変換されるため、多くの文字列変換が発生します。これらの値は一時的に格納する必要があり、インデックスを作成しないため、変換を除いて、ACT.TRANDATE のインデックスは使用されなくなります。これはおそらく、説明計画の最後にかなり高価な「結合バッファーの使用」を引き起こしている可能性があります。

代わりに、文字列 '2013-05-09' を日付値に変換し、この値をクエリの定数またはパラメーターとして使用します。

もう 1 つすべきことは、個別の列に対して個別のインデックスを作成するのではなく、where および/または結合で使用される列のグループに対して 1 つのインデックスを作成することです。たとえば、この部分:

AD.ENTITY = 'APPLICANT' AND 
AD.ENTITYCODE = AP.CODE AND 
AD.VILLAGE_CODE = VI.CODE

列 ENTITY、ENTITYCODE、および VILLAGE_CODE に 1 つのインデックスをまとめて配置する方が、それぞれに個別のインデックスを配置するよりも効率的です。また、他の列も含めると役立つ場合があります。

最後に、列または列の組み合わせが一意であることが保証されている場合は、一意のインデックスを作成します。選択ではわずかに高速です。

一般的なアドバイス: 古い結合構文と ANSI 結合を混在させないでください。クエリが読みにくくなります。

これらのヒント (最後のものを除く) はクエリを高速化するはずですが、データの量、ハードウェア、および負荷によっては、それでも遅くなる可能性があります。

于 2013-06-19T13:51:30.757 に答える