2016-11-19 18 views
0

次のクエリに問題があります。データベーステーブルからログレコードを選択します。非常に遅いMySQLクエリ(20〜60秒!) - なぜですか?

SELECT paymentslog.*, user.username, user.usergroupid, user.displaygroupid, 
     purchase_temp.threadid 
    FROM " . TABLE_PREFIX . "paymentslog AS paymentslog 
    LEFT JOIN " . TABLE_PREFIX . "user AS user 
     ON (paymentslog.userid = user.userid) 
    LEFT JOIN " . TABLE_PREFIX . "paymenttransaction AS paymenttransaction 
     ON (paymentslog.transactionid = paymenttransaction.transactionid) 
    LEFT JOIN " . TABLE_PREFIX . "paymentinfo AS paymentinfo 
     ON (paymenttransaction.paymentinfoid = paymentinfo.paymentinfoid) 
    LEFT JOIN " . TABLE_PREFIX . "purchase_temp AS purchase_temp 
     ON (paymentinfo.hash = purchase_temp.hash) $filterlogs_where 
    GROUP BY paymentslog.logid 
    ORDER BY paymentslog.dateline DESC 
    LIMIT $startat, $perpage 
  • すべての加入は、アクセスに必要とされ、ユーザ名にアクセスするためのユーザー表との結合を除いてSELECTにスレッドID usergroupid、それが実行するために20秒を必要として
  • をdisplaygroupid(!)、そして私の試し中これを修正するには、(paymentlogテーブルの)transactionidカラムのINDEXを追加した後、60秒!
  • 何らかの理由で、それは特定の行を複数回返した、と私はそれをすることによって、「paymentslog.logid BY GROUP」

を追加する固定このような理由のために私はそれに気づく必要があります:
- $ filterlogs_whereをPHP変数にはクエリのWHEREがあります(私はpaymentslogのためにphpの異なるフィルタを使ってビルドします)。 デフォルトでは、$ filterlogs_whereの値は「1 = 1」です。フィルタを適用する必要がある場合は、。=「AND paymentslog.userid = X」などを追加します。

とても遅いですか?
私は数秒またはミリ秒で実行されるより複雑なクエリを見て、書き込んだと思います。上記のクエリでなぜこの問題が発生するのですか?

+0

ハッシュで結合することは可能ですが、整数だけで結合するほうがはるかに高速です。どのくらいのデータが話しているのか、あなたはそれを私たちに伝えていませんでした。 – Xorifelse

+5

整数への結合は部分的に高速かもしれませんが、それだけです。関連するすべてのテーブルのCREATE TABLEステートメントと上記クエリのEXPLAINを使わないと、この問題を解決することはできません。 – Strawberry

+0

@ Xorifelse - 'HASH'インデックスはありません。とにかく、ハッシュはBTreeよりわずかに速いだけです。 –

答えて

0

まず、同じスキーマを持つ複数のテーブルを持たないように注意する必要があります。それは通常、悪いデザインです。

本当にLEFTが必要ですか?つまり、 '右'テーブルに何もない場合でも行が返されますか?そうでない場合は、単にJOINを使用してください。

LEFTsを取り除くと、GROUP BYがなくなることがあります。結合の後にGROUP BYが続くと、通常、「行数を膨らませ」、その後に「by by group by by」が発生します。これにより、処理中に巨大な一時テーブルが作成され、処理が遅くなります。

次に、Pagination via Offsetが問題であることを指摘する必要があります。長いクエリ時間がかかることがよくあります。しかし、この技術を可能にするには、GROUP BYを取り除く必要があります。

短いエイリアスを使用してください。

今、あなたの詳細に戻って...さて、最初に上記のことに取り組んでください。そして、SHOW CREATE TABLEを供給してください。次に、このようなものが高速化します。

SELECT ... 
    FROM (SELECT id 
       ORDER BY dateline DESC 
       LIMIT $startat, $perpage) AS pl 
    JOIN user ON ... 
    JOIN ... 
    ORDER BY dateline DESC; -- yes, needs repeating 
+0

こんにちはリッキーと分析の返信をありがとう!あなたの例を理解することができたので、私は次のクエリを書いた:http://pastebin.com/GQAWe9AZそれは正しいですか?それは多くのレコードで正しい結果を返すようだが、2レコードのテストでは誰も出現しない。長いエイリアスには申し訳ありませんが、すぐに修正されます。 – user3594130

+0

"LEFT"が必要なのかもしれません。 (私はクエリの_intent_を理解していません。) –

+0

ok done!クエリは完璧に動作します、非常にありがとう:) – user3594130

関連する問題