2009-05-07 23 views
0

私は現在、いくつかの最適化が必要なWebサイトで作業しています...フロントページには約15-20秒かかるので、いくつかの最適化がうまくいくと思いました。ここでMySQLクエリの最適化

はMySQLのスロークエリログに現れた1つのクエリです:(〜207Kライン - 電子メールとプロファイルが含まれています)profil_perso

SELECT a.user,a.id 
FROM `profil_perso` pp 
INNER JOIN `acces` a ON pp.parrain = a.id 
INNER JOIN `acces` ap ON ap.id = pp.id 
WHERE pp.parrain_visibilite = '1' 
    AND a.actif = 1 
GROUP BY a.id 
ORDER BY ap.depuis DESC LIMIT 15; 

主キーでperso_idがあり、また、そこにあるid (外部キー)+ parrain(リファラー)+ parrain_visibilite(リファラーが示されています)がインデックスです。 acces

主キーでidがあり、また

にベンチマークをインデックス化された(登録日)がdepuisされ、実際にこれを示しています

初回:1.94532990456
最終時間:1.94532990456を
平均時間:0.0389438009262

私はこのようにそれを入れてみました:

それでも
SELECT DISTINCT a.id, a.user 
FROM `profil_perso` pp 
LEFT JOIN `acces` a ON pp.parrain = a.id 
WHERE pp.parrain_visibilite = 1 
    AND a.actif = 1 
    AND pp.id != 0 
ORDER BY pp.id DESC LIMIT 15; 

ベンチマークショーこの:

初回:1.96376991272
最終時間:1.96376991272
平均時間:0.0393264245987

クエリ時間を下げるためにどれヒント?

ここで完全なインデックスです:

ACCES:

id (primary) 
derniere_visite -- last visit 
pays_id -- country_id 
depuis -- registration time 
perso_id -- foreign key to profil_perso primary key 
actif -- account status 
compte_premium -- if account is premium 

profil_perso:

perso_id (primary) 
id -- foreign key to acces primary key 
genre -- gender 
parrain_visibilite -- visibility of referer 
parrain -- referer 
parrain_contexte 
telephone 
orientation 
naissance -- birthdate 
photo -- if it has a picture 
+0

完全なインデックスを3つのテーブルに投稿してください。それは私の最高の推測ですが、私はそれらを確認する必要があるでしょう。 – MBCook

+0

これらはすべてacces.id、acces.ap acces.parrainのインデックスに登録されていますか? – THEn

+0

出力を希望するものを説明できる場合にも役立ちます – Greg

答えて

3

実行EXPLAIN SELECT DISTINCT a.id .....;

これは、あなたが、インデックスなど不足している可能性があり、どこを表示するのに役立ちますが、

+0

EXPLAINコマンドの実行に同意する前に、最適化のためのクエリを表示することができます。 役に立つリンク http://dev.mysql.com/doc/refman/5.0/en/using-explain.html http://dev.mysql.com/doc/refman/5.0/ja/explain.html –

+0

MySQLがクエリをどのように実行するか分かるまで、ランタイムを最適化するために、より多くのダメージを与える可能性があります。 EXPLAINを使用すると、MySQLがクエリをどのように実行しているかが分かります。 –

+0

+1 説明を実行 –

0

なぜ2つのJOINがここにありますか? profil_perso (parrain, parrain_visibilite)に複合インデックスを作成し、

CREATE INDEX ix_acces_actif_depuis ON acces (actif, depuis) 

を::

acces (actif, depuis)に複合インデックスを作成します

CREATE INDEX ix_profilperso_parrain_parrainvisibilite ON profil_perso (parrain, parrain_visibilite) 

をして、これは試してみてください。

SELECT a.user, a.id 
FROM acces a 
JOIN profil_perso p 
ON  pp.parrain = a.id 
     AND pp.parrain_visibilite = 1 
WHERE a.actif = 1 
ORDER BY 
     a.actif DESC, a.depuis DESC 
LIMIT 15 

は、このクエリは、インデックスを使用します並べ替えを避けるためにactifprofil_persoのインデックスを見つけ、非表示のparrainを見つけて除外します。

ここにLIMIT 15があるので、このクエリは即時になるはずです。

また、あなたのactifフィールドがどのように選択的であるかを知るのに役立ちます。

はこれを理解するには、実行してください:

SELECT COUNT(DISTINCT actif)/COUNT(*) 
FROM acces 
+0

ここに近づいています。クエリの方がはるかに優れていますが、問題があります。クエリは重複を生成します(少数のユーザーを参照することができます...)。グループごとに文を追加すると、クエリは1-2秒にジャンプします。 distinctを使用することはさらに悪化します。 – Erick

+0

サンプルデータを投稿していただけますか? – Quassnoi

0

適切answerr(複数可)データの分布にできるだけ多く(レコード数、フィールドのカーディナリティとフィールドの組み合わせなど)AMDのスキーマに依存、クエリ式のように。その情報があっても、私たちはテストのための提案だけを提供することができ、テストのためのより多くの提案につながります。

しかし、関連するテーブルのスキーマと、現在のEXPLAIN(twise、second、およびfirst resultsの実行)の結果を含む最初のカットから開始することができます。

0

一般的に言えば、プライマリキーだけでなく、テーブル結合で使用される外部キーに対して、あなたのindeciesが正しく設定されていることを確認する必要があります。

さらに、フィルタリング/オーダーするフィールドには、通常、インデックスを定義することをお勧めします。これらのフィールドが適切に設定されていることを確認してください。

しかし、ここで大きなパフォーマンスが得られるのは、最後に挿入された15レコードを取得するために207kレコードをソートしているということでしょう。別の方法で同じ結果を達成できますか?