0

私は長い間共有ホスティングを利用しており、同じクエリを何ヶ月も問題なく実行しています。突然、ホストから、「データベースが過度のプロセッサ時間を消費していることが判明した」ため、データベースにブロックを配置したというメールが届きました。私が理解していないのは、なぜ今なのか?とにかく、VPSに行く必要があるのではないかと思いました。VPS でサイトを立ち上げようとすると、すぐにサイト全体でメモリ不足の制限エラーが発生し、クラッシュしました。しばらくの間、まったくサイトにアクセスしているときに接続がタイムアウトしました。

私のテーブルはどれも非常に大きく、10,000 行を超えません。以下は、元のホストから送られてきたものです。

DB_USER: my_user -- TOTAL_CONNECTIONS: 37 -- CONNECTED_TIME: 4906 --
CPU_TIME: 1920 -- TABLE_ROW_READS: 79999077 -- SELECT_COMMANDS: 214 --
UPDATE_COMMANDS: -- BUSY_TIME: 4879 -- BYTES_SENT: 252225 --
BYTES_RECEIVED: 105418 -- WAIT_TIME (IO): 2959 

表の行は 79,999,077?? と表示されます 真剣に、それはどのように機能しますか。私のテーブルはすべて小さいです。あまりトラフィックがありません。1日100~150人くらいかな。しかし、新しいサーバーにサイトを配置した直後にサイトが完全に停止したため、それは問題ではないようです. これは、データベースがダウンしているというメールに含まれていたクエリです。私を殺しているのは本当にこの1つのクエリだけですか? 文字通り何ヶ月も問題なく稼働しています。

SELECT `Person`.`first_name`, `Person`.`last_name`,`Person`.`id`,`Upload`.`path`,`TeacherBiography`.`final_biography`, `TeacherPhilosophy`.`final_philosophy`
FROM `my_database`.`people` AS `Person`
LEFT JOIN `my_database`.`teacher_drive_cities` AS `TeacherDriveCity`
    ON (`TeacherDriveCity`.`person_id` = `Person`.`id`)
LEFT JOIN `my_database`.`instruments_people` AS `InstrumentsPerson`
    ON (`InstrumentsPerson`.`person_id` = `Person`.`id`)
LEFT JOIN `my_database`.`instruments` AS `Instrument`
    ON (`Instrument`.`id` = `InstrumentsPerson`.`instrument_id`)
LEFT JOIN `my_database`.`teachers` AS `Teacher`
    ON (`Teacher`.`person_id` = `Person`.`id`)
LEFT JOIN `my_database`.`uploads` AS `Upload`
    ON (`Upload`.`person_id` = `Person`.`id`)
LEFT JOIN `my_database`.`teacher_biographies` AS `TeacherBiography`
    ON (`TeacherBiography`.`person_id` = `Person`.`id`)
LEFT JOIN `my_database`.`teacher_philosophies` AS `TeacherPhilosophy`
    ON (`TeacherPhilosophy`.`person_id` = `Person`.`id`)
WHERE `TeacherDriveCit! y`.`city` = 'Dana Point'
    AND `TeacherDriveCity`.`state` = 'ca'
    AND `Instrument`.`instrument` = 'saxophone'
    AND `Teacher`.`status` = 6
    AND `Upload`.`description` = 'profile_picture'
    AND `TeacherBiography`.`final_biography` IS NOT NULL
    AND `TeacherPhilosophy`.`final_philosophy` IS NOT NULL
GROUP BY `Person`.`id`
ORDER BY RAND() ASC
LIMIT 3 

order by rand() は遅いと聞いたことがありますが、1 回の呼び出しでサーバー全体がクラッシュするとは思いませんでした。ここで何か不足していますか?どんな助けでも大歓迎です!私のサイトは 24 時間ダウンしており、そこからの収入で生活しています。ありがとう!

編集:クエリの説明は次のとおりです。

1   SIMPLE  TeacherBiography    ALL NULL    NULL    NULL    NULL    41    Using where; Using temporary; Using filesort
1   SIMPLE  TeacherPhilosophy   ALL NULL    NULL    NULL    NULL    41  Using where; Using join buffer
1   SIMPLE  Upload              ALL NULL    NULL    NULL    NULL    166 Using where; Using join buffer
1   SIMPLE  Teacher             ALL NULL    NULL    NULL    NULL    381 Using where; Using join buffer
1   SIMPLE  InstrumentsPerson   ALL NULL    NULL    NULL    NULL    647 Using join buffer
1   SIMPLE  Instrument  eq_ref  PRIMARY PRIMARY 4   yml_yml.InstrumentsPerson.instrument_id 1   Using where
1   SIMPLE  Person  eq_ref  PRIMARY PRIMARY 4   yml_yml.TeacherPhilosophy.person_id     1   Using where
1   SIMPLE  TeacherDriveCity    ALL NULL    NULL    NULL    NULL    7489    Using where; Using join buffer

簡単に読めるようにフォーマットされていないことは知っています...表にする方法と、ここにないものを知りません。ごめん!

4

1 に答える 1

1

クエリに影響を与える可能性のあるものはたくさんあります。を使用するとEXPLAIN、パフォーマンスに最も影響を与える問題が明らかになります。

ただし、一般的なガイドラインは次のとおりです。

  • すべてのテーブルに、テーブルの結合に使用されるフィールドのインデックスがあることを確認してください。
  • なぜ句LEFT JOINの具体的な値を使用してフィルタリングするのですか?外部結合を使用すると、句WHEREの条件によって後でフィルタリングおよび破棄される行の数が増加します。WHERE
  • フィルタリングに使用されるすべての列がインデックスでカバーされていることを確認してください。しかし、また、なぜテキスト値でフィルタリングするのですか?都市、州、および機器のフィールドがインデックスでカバーされている場合でも、整数を比較するよりも文字列を比較する方が処理に時間がかかります。
  • Person.idランダムに注文する場合、なぜグループ化するのですか?グループ化により、テーブルの結合のために一時テーブルが必要になる可能性が最も高いソート操作が強制されます。

今これについても考えてください:

データベースが一般的に結合を処理する方法は、各テーブルのすべての行を結合してから、結合条件を満たさない組み合わせを破棄することです。そのため、結合フィールドにインデックスを設定することが非常に重要です。この方法では、組み合わせで両方のテーブルのすべてのフィールドを含む一時テーブルではなく、インデックスキーが使用されるためです。これは、以前に破棄された可能性LEFT JOINのある行の組み合わせ(句内)を使用せず、後で破棄する理由でもあります。WHERE

このクエリが何をしているのか、そしてなぜそれがパフォーマンスに影響を与えているのかを理解するには、次のように計算します。

Total rows to filter = Number of rows in table Person
 * Number of rows in table TeacherDriveCity
 * Number of rows in table Instrument
 * Number of rows in table Teacher
 * Number of rows in table Upload
 * Number of rows in table TeacherBiography
 * Number of rows in table TeacherPhilosophy

それは非常に大きな数字になると確信しています。

EXPLAIN解釈

投稿されEXPLAINた結果から、それは非常に悪いです:

  • 前述のように、ALLjoinの下のすべての値typeは、MySQLが全表スキャンを実行していることを意味します。つまり、テーブル上のすべての行を読み取る必要があります。これは非常に、非常に悪いです。
  • ほとんどの結合条件でNULLunderによって明らかにされたように、使用可能なインデックスはありません。possible_keysこれは、MySQLがテーブルスキャンを実行するもう1つの理由です。必要な行をフィルタリングするには、結合されたすべての行を調べる必要があります。

最悪の部分はとによるフィルタリングだと思いcityますstate。結合がない場合、これら2つのフィールドによる単純なルックアップでは、TeacherDriveCityMySQLが潜在的に7489行をルックアップする必要があります。言うまでもなく、両方のフィールドは文字列を保持します。

クイックフィックス

JOINおよびWHERE句で使用されるすべての列にインデックスを追加します。ただし、およびLEFT以外のテーブルでは外部()結合を使用しないことを検討してください。TeacherBiographyTeacherPhilosophy

于 2012-10-12T22:29:44.347 に答える