1

このクエリを最適化する方法があるかどうか知りたいです:

SELECT
    jdc_organizations_activities.*,
    jdc_organizations.orgName, 
    CONCAT(jos_hpj_users.firstName, ' ', jos_hpj_users.lastName) AS nameContact  
FROM jdc_organizations_activities
LEFT JOIN jdc_organizations ON jdc_organizations_activities.organizationId =jdc_organizations.id
LEFT JOIN jos_hpj_users ON jdc_organizations_activities.contact = jos_hpj_users.userId
WHERE jdc_organizations_activities.status LIKE 'proposed'  
ORDER BY jdc_organizations_activities.creationDate DESC LIMIT 0 , 100 ;

テーブル情報

クエリログが表示されたら:

 Query_time: 2  
 Lock_time: 0  
 Rows_sent: 100  
 Rows_examined: **1028330**

クエリプロファイル:

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

2)これらのテーブルには多くの挿入と更新があることを念頭に置いて、テーブルにインデックスを付ける必要があります。

Tizagチュートリアルから:

インデックスは、MySQLテーブルで有効にしてパフォーマンスを向上させることができる特別なものですが、いくつかの欠点があります。新しいインデックスを作成すると、MySQLは、テーブルに変更が加えられるたびに更新する必要がある情報の個別のブロックを構築します。これは、テーブルのエントリを絶えず更新、挿入、および削除している場合、パフォーマンスに悪影響を与える可能性があることを意味します。

インデックスを追加し、lower()、group by、およびワイルドカードを削除した後に更新します

時間: 0.855ms

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

4

4 に答える 4

4

次の場所にインデックスを追加します(まだ追加していない場合)。

テーブル:jdc_organizations_activities

  • の単純なインデックスcreationDate
  • の単純なインデックスstatus
  • の単純なインデックスorganizationId
  • の単純なインデックスcontact

そして、関数の呼び出しを削除し、またはLOWER()を使用してクエリを書き直します。このテーブルに定義した照合に依存しますが、大文字と小文字を区別しない場合(のように)、同じ結果が表示されます。詳細については、MySQLのドキュメントをご覧ください:大文字と小文字の区別=LIKElatin1

SELECT a.*
     , o.orgName
     , CONCAT(u.firstName,' ',u.lastName) AS nameContact  

FROM jdc_organizations_activities AS a
  LEFT JOIN jdc_organizations AS o
    ON a.organizationId = o.id 
  LEFT JOIN jos_hpj_users AS u
    ON a.contact = u.userId

WHERE a.status LIKE 'proposed'     --- or (a.status = 'proposed')

ORDER BY a.creationDate DESC 
LIMIT 0 , 100 ;

実行計画を(現在のように)投稿し、これらの変更を行った後は便利です。


アップデート

の複合インデックス(status, creationDate)は、単純な。ではなく、(Darhazerが提案したように)このクエリに適している場合があります(status)。しかし、これはもっと推測の仕事です。計画を投稿すると(実行後にEXPLAIN query)、より多くの情報が提供されます。

また、次の(主キー)インデックスがすでにあると仮定しました。

  • jdc_organizations.id
  • jos_hpj_users.userId
于 2011-07-04T12:17:30.977 に答える
2

EXPLAINからの結果を投稿する一般的に、、のインデックスjdc_organizations_activities.organizationId、.statusjdc_organizations_activities.contactの複合インデックス、およびjdc_organizations_activitiesjdc_organizations_activities.creationDate

一定のルックアップにLIKEクエリを使用している理由(ワイルドカードシンボルがないか、クエリを編集した可能性があります)ステータスのインデックスはLIKE'proposed%'には使用できますが、LIKE'%proposed%には使用できません'-後者の場合、creationDateにインデックスのみを残す方がよい

于 2011-07-04T11:48:22.573 に答える
1

これらのテーブルにはどのようなインデックスがありますか?具体的には、jdc_organizations_activities.creationDateにインデックスを付けましたか?

また、なぜjdc_organizations_activities.idでグループ化する必要があるのですか?これは行ごとに一意ではありませんか、それとも組織に複数の連絡先を設定できますか?

于 2011-06-30T18:27:27.070 に答える
1

lower()速度が遅いのは、mysqlをすべての行に適用する必要があるためです。解決策は、lowerの結果を格納する新しい列を作成し、その列にインデックスを付けることです。また、トリガーを使用して、ソリューションをより豪華にしましょう。OK、ここに行きます:

a)ステータスの下位バージョンを保持する新しい列を追加します(このvarcharをステータスと同じ幅にします):

ALTER TABLE jdc_organizations_activities ADD COLUMN status_lower varchar(20);

b)新しい列にデータを入力します。

UPDATE jdc_organizations_activities SET status_lower = lower(status);

c)新しい列にインデックスを作成します

CREATE INDEX jdc_organizations_activities_status_lower_index
    ON jdc_organizations_activities(status_lower);

d)新しい列の値を正しく保つためのトリガーを定義します。

DELIMITER ~;
CREATE TRIGGER jdc_organizations_activities_status_insert_trig
BEFORE INSERT ON jdc_organizations_activities
FOR EACH ROW
BEGIN
    NEW.status_lower = lower(NEW.status);
END;

CREATE TRIGGER jdc_organizations_activities_status_update_trig
BEFORE UPDATE ON jdc_organizations_activities
FOR EACH ROW
BEGIN
    NEW.status_lower = lower(NEW.status);
END;~
DELIMITER ;

これでクエリが飛ぶはずです。

于 2011-07-04T12:29:24.193 に答える