4

順序付けなしで非常にうまく実行される多くの結合を含む非常に複雑なクエリがあります。しかし、自分のフィールドのいずれかで注文しようとするとすぐに、実行が非常に遅くなり、完了するまでに約 30 秒かかります。

クエリは次のとおりです。

SELECT SQL_NO_CACHE *
FROM et_order

INNER JOIN et_order_type ON et_order.type_id = et_order_type.id
INNER JOIN et_order_data ON et_order.id = et_order_data.order_id
INNER JOIN et_user et_user_consultant ON et_order.user_id_consulting = et_user_consultant.id
INNER JOIN et_customer ON et_order.customer_id = et_customer.id
INNER JOIN et_appointment ON et_order.appointment_id = et_appointment.id
INNER JOIN et_order_status order_status ON et_order.order_status_id = order_status.id
INNER JOIN et_status glass_r_status ON et_order_data.status_id_glass_r = glass_r_status.id
INNER JOIN et_status glass_l_status ON et_order_data.status_id_glass_l = glass_l_status.id

ORDER BY et_order.id DESC 

LIMIT 50

元のクエリはさらに大きく、さまざまな WHERE 操作も含まれていますが、条件のない基本クエリでさえ、不当に遅くなります。ORDER BY et_order.id DESC を削除すると、クエリのフェッチに約 0.01 秒かかります。

元のクエリでは、必要なすべてのフィールドを個別に選択します。ステートメントを読みやすくするために、「SELECT *」に変更しました。

Explain Select により、次の結果が得られます。

+----+-------------+--------------------+--------+ -------------------------------------------------- --------------+-------------+------ ---+---------------------------------------------+---- ---+---------------------------------+
| | ID | select_type | テーブル | タイプ | 可能な_キー | キー | key_len | 参照 | 行 | 行 エクストラ |
+----+-------------+--------------------+--------+ -------------------------------------------------- --------------+-------------+------ ---+---------------------------------------------+---- ---+---------------------------------+
| | 1 | シンプル | et_customer | すべて | プライマリ | ヌル | ヌル | ヌル | 59750 | 一時的な使用; ファイルソートの使用 |
| | 1 | シンプル | et_order | 参照 | PRIMARY,customer_id,appointment_id,user_id_consulting,order_status_id,type_id | 顧客ID | 4 | eyetool.et_customer.id | 1 | | |
| | 1 | シンプル | et_user_consultant | eq_ref | プライマリ | プライマリ | 4 | eyetool.et_order.user_id_consulting | 1 | | |
| | 1 | シンプル | et_appointment | 参照 | プライマリ | プライマリ | 8 | eyetool.et_order.appointment_id | 1 | | |
| | 1 | シンプル | et_order_data | 参照 | status_id_glass_l,status_id_glass_r,order_id | order_id | 5 | eyetool.et_order.id | 1 | where | の使用
| | 1 | シンプル | et_order_type | すべて | プライマリ | ヌル | ヌル | ヌル | 4 | where を使用します。結合バッファーの使用 |
| | 1 | シンプル | glass_l_status | eq_ref | プライマリ | プライマリ | 4 | eyetool.et_order_data.status_id_glass_l | 1 | | |
| | 1 | シンプル | 注文状況 | eq_ref | プライマリ、id | プライマリ | 4 | eyetool.et_order.order_status_id | 1 | | |
| | 1 | シンプル | glass_r_status | eq_ref | プライマリ | プライマリ | 4 | eyetool.et_order_data.status_id_glass_r | 1 | | |
+----+-------------+--------------------+--------+ -------------------------------------------------- --------------+-------------+------ ---+---------------------------------------------+---- ---+---------------------------------+
セットで 9 行 (0.00 秒)

私がよく理解していないのは、なぜ Explain select が et_order_type にキーを使用しないと言っているのかということです。たぶん、4行しかないので必要ないから!?

しかし、et_order: KEY type_id( type_id)の type_id にインデックスがあります。

参加と注文に使用しているすべてのキーに(単一の) INDEXを追加しました。これが問題でしょうか?複合インデックスを作成する必要がありますか?

テーブルには、et_order と et_order_data に約 200.000 個のデータセット、et_customer に 60.000 個、et_apointments に 150.000 個のデータセットが含まれています。その他の内容はごくわずかです。

et_order_data と et_order_type を結合するだけでも、非常に時間がかかり、select が et_order_type のキー NULL を示していることを説明します。

EXPLAIN SELECT SQL_NO_CACHE *
FROM et_order

INNER JOIN et_order_type ON et_order.type_id = et_order_type.id
INNER JOIN et_order_data ON et_order.id = et_order_data.order_id

ORDER BY et_order.id DESC

リミット50

+----+-------------+---------------+------+------- ----------+---------+---------+------------------ ---+--------------------+---------------------------------+
| | ID | select_type | テーブル | タイプ | 可能な_キー | キー | key_len | 参照 | 行 | 行 エクストラ |
+----+-------------+---------------+------+------- ----------+---------+---------+------------------ ---+--------------------+---------------------------------+
| | 1 | シンプル | et_order | すべて | PRIMARY,type_id | ヌル | ヌル | ヌル | 162007 | 一時的な使用; ファイルソートの使用 |
| | 1 | シンプル | et_order_data | 参照 | order_id | order_id | 5 | eyetool.et_order.id | 1 | where | の使用
| | 1 | シンプル | et_order_type | すべて | プライマリ | ヌル | ヌル | ヌル | 4 | where を使用します。結合バッファーの使用 |
+----+-------------+---------------+------+------- ----------+---------+---------+------------------ ---+--------------------+---------------------------------+

et_order および et_order_typeのテーブル構造は、http: //pastebin.com/PED6Edyxで確認できます。

クエリを最適化するためのヒントはありますか?

次のようなサブクエリで注文してみました:

SELECT SQL_NO_CACHE *
FROM (SELECT * FROM et_order ORDER BY et_order.id DESC) as et_order
INNER JOIN et_order_type ON et_order.type_id = et_order_type.id
...

これは非常に迅速でしたが、et_order だけでなく、結合されたテーブルのフィールドでも順序付けを行う必要があるため、まったく役に立ちません。

よろしくお願いします。

アップデート:

奇妙なことに、すべての内部結合を左のものに変更すると、チャームのように機能します...

SELECT SQL_NO_CACHE * FROM et_order LEFT JOIN et_order_type ON et_order.type_id = et_order_type.id LEFT JOIN et_order_data ON et_order.id = et_order_data.order_id LEFT JOIN et_user et_user_consultant ON et_order.user_id_consulting = et_user_consultant.id LEFT JOIN et_customer ON et_order.id_customer_id.左結合 et_appointment ON et_order.appointment_id = et_appointment.id 左結合 et_order_status order_status ON et_order.order_status_id = order_status.id 左結合 et_status glass_r_status ON et_order_data.status_id_glass_r = glass_r_status.id 左結合 et_status glass_l_status ON et_order_data.status_id_glass_l_status = glass_l

ORDER BY et_order.id DESC LIMIT 50

誰かが理由を知っていますか?

4

1 に答える 1

0

このクエリを試してください

SELECT SQL_NO_CACHE *
FROM et_order
INNER JOIN et_order_type ON et_order.type_id = et_order_type.id
INNER JOIN et_order_data ON et_order.id = et_order_data.order_id
INNER JOIN et_user et_user_consultant ON et_order.user_id_consulting = et_user_consultant.id
INNER JOIN et_customer FORCE INDEX(et_customer.id) ON et_order.customer_id = et_customer.id
INNER JOIN et_appointment ON et_order.appointment_id = et_appointment.id
INNER JOIN et_order_status order_status ON et_order.order_status_id = order_status.id
INNER JOIN et_status glass_r_status ON et_order_data.status_id_glass_r = glass_r_status.id
INNER JOIN et_status glass_l_status ON et_order_data.status_id_glass_l = glass_l_status.id
ORDER BY et_order.id DESC LIMIT 50
于 2013-05-07T13:04:07.657 に答える