0

AES_DECRYPT を他のトリッキーな状況と一緒に使用する必要があるため、長い時間がかかる非常にトリッキーな SQL クエリがあります。まず、クエリは次のとおりです。

SELECT
CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ),
timestamp,
category,
status

FROM email_statuses

WHERE 

timestamp IN (
    SELECT MAX(timestamp)
    FROM email_statuses
    WHERE ( CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ?
        OR CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ? )
    AND category = 'EMAIL_TEMPLATE_01'
)

OR

timestamp IN (
    SELECT MAX(timestamp)
    FROM email_statuses
    WHERE ( CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ?
        OR CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ? )
    AND category = 'EMAIL_TEMPLATE_02'
) 

OR

timestamp IN (
    SELECT MAX(timestamp)
    FROM email_statuses
    WHERE ( CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ?
        OR CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ? )
    AND category = 'EMAIL_TEMPLATE_03'
);

タイムスタンプ IN と表示されている各ブロックでは (... 最初の ? はユーザーのプライマリ メールであり、2 番目の ? はユーザーのセカンダリ メールです。

基本的に、このクエリが行うことは、3 つのメール (カテゴリ = メールの名前) のそれぞれの最新のステータスのリストを返すことです。そのユーザーのそれぞれの最新ステータスのみが必要です。たとえば、「email@domain.com」を使用したクエリの結果は次のようになります。

email---------------timestamp----------category-------------status---------  

email@domain.com----0000-00-00 etc-----EMAIL_TEMPLATE_01----Sent  
email@domain.com----0000-00-00 etc-----EMAIL_TEMPLATE_02----Open & click through  
email@domain.com----0000-00-00 etc-----EMAIL_TEMPLATE_03----Open

現在、email_status テーブルのレコード数は 1000 を超えているため、ステータス テーブルのすべての暗号化された電子メール行に対して convert/AES_DECRYPT を実行する必要があるため、クエリに最大 30 秒かかります。これを最適化する方法について何か考えはありますか? 私は SQL の専門家ではありません。

4

3 に答える 3

2

すべてのinステートメントを結合して結合します。

SELECT distinct CONVERT( AES_DECRYPT( es.email, '$key' ) USING UTF8 ),
       es.timestamp, es.category, es.status
FROM email_statuses es join
     (select category, MAX(timestamp) as maxtimestamp
      from email_statuses
      where ( CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ? or
            CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ? ) and
            category in ('EMAIL_TEMPLATE_01', 'EMAIL_TEMPLATE_02', 'EMAIL_TEMPLATE_03')
      group by category
     ) csum
     on es.timestamp = csum.category

distinct複数のカテゴリで一致する場合に備えて、 も含めました。

于 2013-03-20T20:18:57.783 に答える
2

実行できる最適化の 1 つは、次のことです。

  1. まず、電子メール アドレスを提供するパラメータを AES 暗号化します。
  2. 各クエリを書き直して、暗号化されたパラメーターに対してデータベース テーブルの実際の値をテストします。

したがって、各クエリは次のようになります。

// precompute the encrypted parameter (maybe on the PHP side, before executing the query)

SELECT MAX(timestamp)
FROM email_statuses
WHERE email = ?              -- here pass the already encrpyed paramter
    OR email = ?             --       .. same here
AND category = 'EMAIL_TEMPLATE_02'

基本的な考え方は、クエリ内の各テストでand AES_ENCRYPTorを実行しないようにすることです。AES_DECRYPTむしろ、パラメータを暗号化し、それを使用してテストする..

于 2013-03-20T20:16:55.480 に答える
1

3 つのサブクエリがあるため、それぞれがすべてのレコードを復号化する必要があります。1 つのサブクエリでこれを行うことができれば、3 分の 1 の時間がかかるはずです。

SELECT CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ),
       timestamp, category, status
FROM email_statuses
WHERE 

timestamp IN (
    SELECT MAX(timestamp)
    FROM email_statuses
    WHERE ( CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ?
         OR CONVERT( AES_DECRYPT( email, '$key' ) USING UTF8 ) = ? )
        AND category IN ('EMAIL_TEMPLATE_01', 'EMAIL_TEMPLATE_02', 'EMAIL_TEMPLATE_03')
    GROUP BY category
)
于 2013-03-20T20:23:35.710 に答える