0

レポートツールについて、mysqlで次のクエリを作成しました。

インライン選択です。クエリは正しい結果を返しますが、実行に時間がかかります。誰かがそれをより効率的にするために別の方法を提案したり、クエリを書いたりできますか?

SELECT z.name1, (
       SELECT COUNT( AES_DECRYPT( l.answertext,  "aaa" ) ) 
       FROM household_data l
       INNER JOIN sms_household m 
             ON l.prim_key = m.hhid
       INNER JOIN sms_psu n 
             ON n.psu = m.psu
             AND n.state = m.state
             AND n.district = m.district
       INNER JOIN (
             SELECT p.prim_key, p.fieldname
             FROM household_data p
             WHERE p.basicname =  'Q05'
             AND AES_DECRYPT( p.answertext,  "aaa" ) =2
       ) women 
             ON l.prim_key = women.prim_key
             AND SUBSTR( l.fieldname, 5, 1 ) = SUBSTR( women.fieldname, 5, 1 ) 
             WHERE l.basicname =  'Q08' AND AES_DECRYPT( l.answertext,  "aaa" ) = 14
             AND z.psu = n.psu
             [AND n.state IN ( {state} )] 
             [AND n.district IN ( {district} )]
) female14, (
       SELECT COUNT( AES_DECRYPT( l.answertext,  "aaa" ) ) 
       FROM household_data l
       INNER JOIN sms_household m ON l.prim_key = m.hhid
       INNER JOIN sms_psu n 
             ON n.psu = m.psu
             AND n.state = m.state
             AND n.district = m.district
       INNER JOIN (
             SELECT p.prim_key, p.fieldname
             FROM household_data p
             WHERE p.basicname =  'Q05'
             AND AES_DECRYPT( p.answertext,  "aaa" ) =2
       ) women 
             ON l.prim_key = women.prim_key
             AND SUBSTR( l.fieldname, 5, 1 ) = SUBSTR( women.fieldname, 5, 1 ) 
             WHERE l.basicname =  'Q08' AND AES_DECRYPT( l.answertext,  "aaa" ) = 15
             AND z.psu = n.psu
             [AND n.state IN ( {state} )] 
             [AND n.district IN ( {district} )]
) female15, (
       SELECT COUNT( AES_DECRYPT( l.answertext,  "aaa" ) ) 
       FROM household_data l
       INNER JOIN sms_household m 
             ON l.prim_key = m.hhid
       INNER JOIN sms_psu n 
             ON n.psu = m.psu
                    AND n.state = m.state
                           AND n.district = m.district
       INNER JOIN (
             SELECT p.prim_key, p.fieldname
             FROM household_data p
             WHERE p.basicname =  'Q05'
             AND AES_DECRYPT( p.answertext,  "aaa" ) =2
       ) women 
             ON l.prim_key = women.prim_key
             AND SUBSTR( l.fieldname, 5, 1 ) = SUBSTR( women.fieldname, 5, 1 ) 
       WHERE l.basicname =  'Q08' AND AES_DECRYPT( l.answertext,  "aaa" ) =16
       AND z.psu = n.psu
       [AND n.state IN ( {state} )] 
       [AND n.district IN ( {district} )]
) female16, (
       SELECT count(AES_DECRYPT(household_data.answertext , "aaa")) * 100 / (
              SELECT count(AES_DECRYPT(household_data.answertext , "aaa"))
              FROM household_data 
              INNER JOIN sms_household
              INNER JOIN sms_psu
                    ON sms_psu.psu = sms_household.psu
                    AND sms_psu.state = sms_household.state
                    AND sms_psu.district = sms_household.district
              WHERE  basicname = 'Q07_year' AND z.psu= sms_psu.psu
              [AND sms_psu.state IN ( {state} )] 
              [AND sms_psu.district IN ( {district} )]
              )
       FROM household_data 
       INNER JOIN sms_household
       INNER JOIN sms_psu
             ON sms_psu.psu = sms_household.psu
             AND sms_psu.state = sms_household.state
             AND sms_psu.district = sms_household.district
       WHERE AES_DECRYPT(household_data.answertext , "aaa") = 9998 
       AND basicname = 'Q07_year'
       AND z.psu = sms_psu.psu
       [AND sms_psu.state IN ( {state} )] 
       [AND sms_psu.district IN ( {district} )]
) PercYearDontKnow
FROM household_data x
INNER JOIN sms_household y 
      ON x.prim_key = y.hhid
INNER JOIN sms_psu z 
      ON y.psu = z.psu
AND z.state = y.state
AND z.district = y.district
WHERE 1=1 
[AND y.state IN ( {state} )] 
[AND y.district IN ( {district} )
GROUP BY z.psu
4

2 に答える 2

1

投稿を編集して、クエリ構造をより明確にしました。独自のコードで同じことを行うことをお勧めします。

再構築後、female14、female15、female16 を検索するためにクエリの一部を繰り返していることが明らかになります。

次のように、その部分に対して別のクエリを作成する必要があるかもしれません。

   SELECT n.name1, 
          n.psu, 
          AES_DECRYPT( l.answertext,  "aaa" ) AS answer, 
          COUNT(*) as count
   FROM household_data l
   INNER JOIN sms_household m 
         ON l.prim_key = m.hhid
   INNER JOIN sms_psu n 
         ON n.psu = m.psu
         AND n.state = m.state
         AND n.district = m.district
   INNER JOIN (
         SELECT p.prim_key, p.fieldname
         FROM household_data p
         WHERE p.basicname =  'Q05'
         AND AES_DECRYPT( p.answertext,  "aaa" ) =2
   ) women 
         ON l.prim_key = women.prim_key
         AND SUBSTR( l.fieldname, 5, 1 ) = SUBSTR( women.fieldname, 5, 1 ) 
         WHERE l.basicname =  'Q08' 
         AND AES_DECRYPT( l.answertext,  "aaa" ) = 14
         [AND n.state IN ( {state} )] 
         [AND n.district IN ( {district} )]
   GROUP BY n.psu, AES_DECRYPT( l.answertext,  "aaa" )

このクエリでは、Q08 の回答の概要とその番号が表示されます。

その後、PercYearDontKnow に対して別のクエリを作成できます。後でデータを再構築する方が、frankenquery よりも高速になると思います。または、上記のクエリを SQL ビューとしてコーディングし、それをより大きなクエリにアセンブルします。

ちなみに、 を使用する代わりに、COUNT( AES_DECRYPT( l.answertext, "aaa" ) )おそらく を使用できますCOUNT(*)。これは、復号化関数が呼び出される頻度が少なくなることを意味します。

もう 1 つのオプションはSELECT AES_ENCRYPT( "2", "aaa" )、Q08 を比較するときにその値を定数として使用することです。そうすれば、各フィールドを繰り返し復号化する必要がなくなります。

その後、ここで別の回答にある最適化のアドバイスに従います。具体的には、実行パスを見て、インデックスを追加する必要があるかどうかを確認します。

于 2012-09-04T09:52:19.983 に答える
0

醜いもの...私のアドバイス:

  • インデックスをチェックして、パフォーマンスを向上させるために何ができるかを確認してください
  • テーブル構造を確認してください。最も近いものが正しいものであることを確認してください
  • 結合をチェックして、何が変更できるかを確認してください
  • パフォーマンス監視の実行計画を常にチェックする

そしてもちろん、本番環境ではなく、テスト環境ですべてを行うと、面倒になる可能性があります。別のアドバイスとして、一度に 1 ステップずつ実行し、小さな変更をそれぞれチェックして、結果が同じであることを確認してください。結果を保存して比較し、最後に良いものを取得します。

于 2012-09-04T09:07:08.000 に答える