0

私たちの環境:Drupal + MySQL

クエリログを調べると、Drupalコアのnode_load関数から発信された次のクエリにかなりの時間がかかっていることがわかります。

node_loadクエリのEXPLAINは、インデックスがUSERテーブルで使用されていないことを示しています。

mysql> explain SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, 
    n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, 
    r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data 
FROM xyz_node n 
INNER JOIN xyz_users u ON n.uid = u.uid 
INNER JOIN xyz_node_revisions r ON r.vid = n.vid;

+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref          | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
|  1 | SIMPLE      | u     | ALL    | PRIMARY       | NULL    | NULL    | NULL         |  181 |             | 
|  1 | SIMPLE      | n     | ref    | vid,uid       | uid     | 4       | xyz.u.uid |    9 | Using where | 
|  1 | SIMPLE      | r     | eq_ref | PRIMARY       | PRIMARY | 4       | xyz.n.vid |    1 |             | 
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+

何が起こっているのか、そしてMYSQLにこのクエリでインデックスを使用させる方法はありますか?

4

3 に答える 3

3

テーブルは、必ずしもFROM句で指定された順序で結合されるとは限りません。この場合、MySQLはWHERE、クエリに句がない場合、最初にusersテーブルをスキャンしてから、それを他のテーブルと結合するのがおそらく最も速いと判断したようです。

私が最初にすることはANALYZE TABLE、クエリに関係する3つのテーブルすべてで実行することです。これにより、テーブルの統計と保存されているキーの分布が更新され、結合オプティマイザーがより適切な決定を行えるようになります。EXPLAINその後、ステートメントを実行して、変更されているかどうかを確認します。

変更されていない場合は、STRAIGHT_JOINキーワードの使用に頼る必要があるかもしれません。これにより、結合オプティマイザはクエリで指定された正確な順序でテーブルを結合します。これを行う必要があるかどうかを判断するためにrows、結果からすべての値の積を取得しEXPLAIN、それをクエリから返された実際の行数と比較することになっています。したがって、この場合、1629(181x9x1)を実際の行数と比較します。それらが大幅に異なる場合は、aSTRAIGHT_JOINが呼び出される可能性があります(キーワードとして使用されSELECTます。つまり、SELECT STRAIGHT_JOIN n.nid...など)。

余談ですが、MySQLに特定のインデックスを使用するように指示WHEREする方法はありますが、句がないため、現在のように、このクエリのユーザーテーブルでは機能しないと思います。最終的にを使用する場合STRAIGHT_JOINは、それが必要になる可能性がありますが、その場合、ユーザーテーブルが結合の最初のテーブルでない場合、MySQLは主キーを取得する可能性があります。

これに関するさらに役立つ詳細については、EXPLAIN構文ページも参照してください。

このクエリは、それが何であるかについてはそれほど遅くないはずのようには見えませんwhere句がないと、どこかで全表スキャンが期待でき、MySQLはそれを調査した合計行数約1700に抑えています。これは、使用頻度の高いクエリである場合にのみ問題になるようです。その場合WHERE、システム内のすべてのユーザーに影響を与えるクエリの実行を含む(句なしの)基盤となるアーキテクチャを調べることができます。より多くのユーザーが追加されると、重くなるだけです。

于 2009-05-18T21:55:15.490 に答える
1

MySQLはクエリごとにテーブルごとに1つのインデックスしか使用できないため、この一見役に立たない条件をスローするだけで「フリー」範囲のインデックススキャンを取得できる場合があります。

WHERE u.uid > 0

その句をに追加してみてください。おそらく、全表スキャンが「範囲」に変更されます。これは、全表スキャンよりも優れています。

于 2009-05-18T21:58:26.980 に答える
0

これは役に立ちますか?

テーブル ノードで、(uid,vid) ALTER TABLE 'xyz_node' ADD INDEX user_ver( 'uid,'vid' ) にインデックスを作成します (Explain 出力の 2 行目に注意してください。見出しの可能なキーの下に.. vid,uid が表示されます)

于 2009-10-04T02:27:22.070 に答える