web-dev-qa-db-ja.com

ORDERBYを使用するとクエリが遅くなる

これがクエリです(最大のテーブルには約40,000行あります)

SELECT
  Course.CourseID,
  Course.Description,
  UserCourse.UserID,
  UserCourse.TimeAllowed,
  UserCourse.CreatedOn,
  UserCourse.PassedOn,
  UserCourse.IssuedOn,
  C.LessonCnt
FROM
  UserCourse
INNER JOIN
  Course
USING(CourseID)
INNER JOIN
(
  SELECT CourseID, COUNT(*) AS LessonCnt FROM CourseSection GROUP BY CourseID
) C
USING(CourseID)
WHERE 
  UserCourse.UserID = 8810

これを実行すると、非常に高速に実行されます(およそ.05秒)。 13行を返します。

クエリの最後にORDER BY句を追加すると(任意の列で並べ替える)、クエリには約10秒かかります。

現在、このデータベースを本番環境で使用していますが、すべて正常に機能しています。他のすべてのクエリは高速です。

それが何であるかについてのアイデアはありますか? MySQLのクエリブラウザとコマンドラインからクエリを実行しました。どちらの場所も、ORDER BYで非常に遅くなりました。

編集: Tolgahan ALBAYRAKソリューションは機能しますが、なぜ機能するのか誰かが説明できますか?

18
Dude

多分これは役立ちます:

SELECT * FROM (    
     SELECT
      Course.CourseID,
      Course.Description,
      UserCourse.UserID,
      UserCourse.TimeAllowed,
      UserCourse.CreatedOn,
      UserCourse.PassedOn,
      UserCourse.IssuedOn,
      C.LessonCnt
    FROM
      UserCourse
    INNER JOIN
      Course
    USING(CourseID)
    INNER JOIN
    (
      SELECT CourseID, COUNT(*) AS LessonCnt FROM CourseSection GROUP BY CourseID
    ) C
    USING(CourseID)
    WHERE 
      UserCourse.UserID = 8810
) ORDER BY CourseID
17

注文している列はインデックスに登録されていますか?

インデックス作成により、順序付けとフィルタリングが大幅に高速化されます。

7
ceejayoz

serCourse」から選択しています。これは、コースとユーザー(多対多)の間の結合テーブルであると思います。 「UserCourse」テーブルで、注文する必要のある列にインデックスを付ける必要があります。

"CourseIDで並べ替え"にしたい場合は、serCourseテーブルでインデックスを作成する必要があります。

結合テーブル(つまり、UserCourse)に存在しない他の列による順序付けでは、速度を最適化するために、さらに非正規化とインデックス付けが必要になる場合があります結合テーブル上。つまり、結合テーブルにその列のコピーを作成し、インデックスを作成する必要があります。

P.S。 Tolgahan Albayrakによる回答は、この質問には正しいものの、「LIMIT x」クエリを実行している場合、望ましい結果が得られません。

2
Guy

答えが遅すぎることに気づきましたが、同様の問題が発生しました。クエリ時間を秒から5分に増やして順序を追加し、それを高速化するための他のほとんどの提案を試したところ、/ tmpファイルが12Gになることに気付きました。このクエリ。返されるvarchar(20000)フィールドが「トリム(」され、パフォーマンスが劇的に向上するようにクエリを変更しました(数秒に戻ります)。したがって、クエリの一部として大きなvarcharを返すかどうかを確認する価値があると思います。それらを処理します(おそらくsubstring(x、1、length(x))??それらをトリミングしたくない場合。クエリは500k行を返し、/ tmpファイルは各行が約20kのデータを使用していることを示しました。

1
aronp

今日、私は同じ種類の問題に遭遇していました。結合されたテーブルのフィールドで結果セットを並べ替えるとすぐに、クエリ全体がひどく遅くなり、100秒以上かかりました。

サーバーはMySQL5.0.51aを実行していましたが、偶然にも、同じクエリがMySQL5.1を搭載したサーバーで常に実行するはずの速度で実行されていることに気付きました。そのクエリの説明を比較すると、明らかにインデックスの使用法と処理が大幅に変更されていることがわかりました(少なくとも5.0-> 5.1から)。

したがって、このような問題が発生した場合の解決策は、MySQLをアップグレードすることです。

0

データベースの統計を更新しましたか?私は同じようなクエリに遭遇しました。2つの同じクエリがあり、唯一の違いは大文字で、1つは1/2秒で返され、もう1つは5分近くかかりました。統計を更新すると問題が解決しました

0
Fry

同様の質問が前に尋ねられました ここ。

それはあなたにも役立つかもしれません。基本的に、複合インデックスの使用と、orderbyのしくみについて説明します。

0
northpole