10

クエリに時間がかかりすぎるという問題があります(この単純なクエリの場合は2秒以上かかります)。

一見すると、インデックス作成の問題のように見えます。結合されたすべてのフィールドにインデックスが付けられますが、これを高速化するためにインデックスを作成する必要がある他のフィールドが見つかりません。必要なフィールドをクエリに追加するとすぐに、さらに遅くなります。

SELECT  `jobs`.`job_id` AS  `job_id` FROM tabledef_Jobs AS jobs
 LEFT JOIN tabledef_JobCatLink AS jobcats ON jobs.job_id = jobcats.job_id
 LEFT JOIN tabledef_Applications AS apps ON jobs.job_id = apps.job_id
 LEFT JOIN tabledef_Companies AS company ON jobs.company_id = company.company_id
GROUP BY  `jobs`.`job_id` 
ORDER BY  `jobs`.`date_posted` ASC
LIMIT 0 , 50

テーブルの行数(〜):tabledef_Jobs(108k)、tabledef_JobCatLink(109k)、tabledef_Companies(100)、tabledef_Applications(50k)

ここで説明を見ることができます。「一時的な使用」がクエリの速度を低下させているようです。

ここに画像の説明を入力してください

テーブルインデックスのスクリーンショット:

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ここに画像の説明を入力してください

どんな助けでも大歓迎です

答えで編集

@Steve(マークされた回答)のおかげで最終的に改善されたクエリ。最終的に、最終的なクエリは約22秒から約0.3秒に短縮されました。

SELECT `jobs`.`job_id` AS `job_id` FROM
(
 SELECT * FROM tabledef_Jobs as jobs ORDER BY `jobs`.`date_posted` ASC LIMIT 0 , 50
) AS jobs
 LEFT JOIN tabledef_JobCatLink AS jobcats ON jobs.job_id = jobcats.job_id
 LEFT JOIN tabledef_Applications AS apps ON jobs.job_id = apps.job_id
 LEFT JOIN tabledef_Companies AS company ON jobs.company_id = company.company_id
GROUP BY  `jobs`.`job_id` 
ORDER BY  `jobs`.`date_posted` ASC
LIMIT 0 , 50
4

1 に答える 1

7

ええ、私はこれを突き刺します。

クエリ オプティマイザーはインデックスを使用して tabledef_Jobs テーブルに対するクエリを実行できないようです。

オフセット制限があり、これを ORDER BY の組み合わせで結合する前にデータの量を制限できないため、PK で高速な job_id でグループ化する必要がありますが、そのデータ (一時テーブルとfilesort) を実行してから、このデータの大部分を制限して破棄し、最終的に他のすべてをそれに結合します。

「job_id, date_posted」のジョブに複合インデックスを追加することをお勧めします</p>

したがって、最初にベースクエリを最適化します。

SELECT * FROM tabledef_Jobs 
GROUP BY job_id
ORDER BY date_posted
LIMIT 0,50

次に、結合と最終的な構造を組み合わせて、より効率的なクエリを作成できます。

制限のオフセットを再考することを提案せずに、それを手放すことはできません. 初期オフセットが小さい場合はこれで問題ありませんが、オフセットが大きくなり始めると、パフォーマンスの問題の主な原因になる可能性があります。たとえば、これをページネーションに使用しているとしましょう。3,000 ページが必要な場合はどうなりますか?

LIMIT 3000, 50

これにより、3050 行が収集され、データが操作されてから、最初の 3000 行が破棄されます。

[編集 1 - 以下のコメントに応じて]

あなたを正しい方向に導くかもしれないいくつかのより多くの情報で展開します. 残念ながら、これを解決する簡単な修正方法はありません。これに対処するには、なぜこれが起こっているのかを理解する必要があります。単純に LIMIT または ORDER BY を削除しても機能しない可能性があり、結局のところ、クエリの一部として削除したくないため、目的のためにそこにある必要があります。

最初に単純な基本クエリを最適化します。これは通常、複数結合されたデータセットを操作するよりもはるかに簡単です。

受け取ったすべてのバッシングにもかかわらず、 filesort には何の問題もありません。これがクエリを実行する唯一の方法である場合があります。多くのパフォーマンスの問題 (特に大規模なデータ セット) の原因になる可能性があることに同意しましたが、それは通常、ファイル ソートのせいではなく、基になるクエリ/インデックス作成戦略のせいです。

MySQL 内では、インデックスを混合したり、同じインデックスの順序を混合したりすることはできません。このようなタスクを実行すると、ファイルソートが発生します。

date_posted でインデックスを作成してから使用することを提案したのはどうですか:

SELECT jobs.job_id, jobs.date_posted, jobcats .*, apps.*, company .* FROM
(
    SELECT DISTINCT job_id FROM tabledef_Jobs 
    ORDER BY date_posted
    LIMIT 0,50
) AS jobs
LEFT JOIN tabledef_JobCatLink AS jobcats ON jobs.job_id = jobcats.job_id
LEFT JOIN tabledef_Applications AS apps ON jobs.job_id = apps.job_id
LEFT JOIN tabledef_Companies AS company ON jobs.company_id = company.company_id
于 2013-03-07T14:29:26.333 に答える