0

私のサイトのホームページには、次のような複雑なクエリがあります。

SELECT karmalog.*, image.title as img_title, image.date_uploaded, imagefile.file_name as img_filename, imagefile.width as img_width, imagefile.height as img_height, imagefile.transferred as img_transferred, u1.uname as usr_name1, u2.uname as usr_name2, u1.avat_url as usr_avaturl1, u2.avat_url as usr_avaturl2, class.title as class_title,forum.id as f_id, forum.name as f_name, forum.icon, forumtopic.id as ft_id, forumtopic.subject
FROM karmalog 
LEFT JOIN image on karmalog.event_type = 'image' and karmalog.object_id = image.id 
LEFT JOIN imagefile on karmalog.object_id = imagefile.image_id and imagefile.type = 'smallthumb'
LEFT JOIN class on karmalog.event_type = 'class' and karmalog.object_id = class.num
LEFT JOIN user as u1 on karmalog.user_id = u1.id
LEFT JOIN user as u2 on karmalog.user_sec_id = u2.id
LEFT JOIN forumtopic on karmalog.object_id = forumtopic.id and karmalog.event IN ('FORUM_REPLY','FORUM_CREATE')
LEFT JOIN forum on forumtopic.forum_id = forum.id
WHERE karmalog.event IN ('EDIT_PROFILE','FAV_IMG_ADD','FOLLOW','COM_POST','IMG_UPLOAD','IMG_VOTE','LIST_VOTE','JOIN','CLASS_UP','CLASS_DOWN','LIST_CREATE','FORUM_REPLY','FORUM_CREATE','FORUM_SUBSCRIBE')
  AND karmalog.delete=0
ORDER BY karmalog.date_created DESC, karmalog.id DESC 
LIMIT 0,13 

正確な詳細については説明しませんが、簡単に説明します。基本的に、これはシステム内で発生したイベントのリストであり、ストリームのようなものです。イベントにはいくつかのタイプがあり、そのタイプに基づいて、さまざまなテーブルから特定のデータを結合する必要があります。

現在、このクエリの実行には 2 秒かかりますが、エントリの量が増えるにつれて時間の経過とともに遅くなります。したがって、私はそれを最適化しようとしています。MYSQL Explain の出力は次のとおりです。

ここに画像の説明を入力

EXPLAIN についての私の理解は、これを理解するにはあまりにも限られています。このクエリを (非正規化するのではなく) そのままにしておくことをお勧めしますが、適切なインデックスまたはその他のクイック ウィンを使用してパフォーマンスを向上させます。この説明の出力に基づいて、フォローアップできるものはありますか?

編集:ここで要求されたように、カルマログテーブルの定義:

CREATE TABLE `karmalog` (
  `id` int(11) NOT NULL auto_increment,
  `guid` char(36) default NULL,
  `user_id` int(11) default NULL,
  `user_sec_id` int(11) default NULL,
  `event` enum('EDIT_PROFILE','EDIT_AVATAR','EDIT_EMAIL','EDIT_PASSWORD','FAV_IMG_ADD','FAV_IMG_ADDED','FAV_IMG_REMOVE','FAV_IMG_REMOVED','FOLLOW','FOLLOWED','UNFOLLOW','UNFOLLOWED','COM_POSTED','COM_POST','COM_VOTE','COM_VOTED','IMG_VOTED','IMG_UPLOAD','LIST_CREATE','LIST_DELETE','LIST_ADMINDELETE','LIST_VOTE','LIST_VOTED','IMG_UPD','IMG_RESTORE','IMG_UPD_LIC','IMG_UPD_MOD','IMG_UPD_MODERATED','IMG_VOTE','IMG_VOTED','TAG_FAV_ADD','CLASS_DOWN','CLASS_UP','IMG_DELETE','IMG_ADMINDELETE','IMG_ADMINDELETEFAV','SET_PASSWORD','IMG_RESTORED','IMG_VIEW','FORUM_CREATE','FORUM_DELETE','FORUM_ADMINDELETE','FORUM_REPLY','FORUM_DELETEREPLY','FORUM_ADMINDELETEREPLY','FORUM_SUBSCRIBE','FORUM_UNSUBSCRIBE','TAG_INFO_EDITED','JOIN') NOT NULL,
  `event_type` enum('follow','tag','image','class','list','forum','user') NOT NULL,
  `active` bit(1) NOT NULL,
  `delete` bit(1) NOT NULL default '\0',
  `object_id` int(11) default NULL,
  `object_cache` varchar(1024) default NULL,
  `karma_delta` int(11) NOT NULL,
  `gold_delta` int(11) NOT NULL,
  `newkarma` int(11) NOT NULL,
  `newgold` int(11) NOT NULL,
  `mail_processed` bit(1) NOT NULL default '\0',
  `date_created` timestamp NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`id`),
  KEY `user_id` (`user_id`),
  KEY `user_sec_id` (`user_sec_id`),
  KEY `image_id` (`object_id`),
  CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE SET NULL,
  CONSTRAINT `user_sec_id` FOREIGN KEY (`user_sec_id`) REFERENCES `user` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
4

3 に答える 3

3
  • まず、で複合インデックスが欠落している可能性があります(event_type, object_id)。2回目の読み取りでは、これを無視してください。他のクエリにはこのようなインデックスが必要な場合がありますが、このインデックスには必要ありません(のためORDER BY ... LIMIT)。

  • 次に、この列にインデックスがありませんdate_createdORDER BYこれにインデックスを追加します。条件も考慮WHEREに入れると、最良のインデックスは、(delete, date_created)または(event, date_created)または(おそらく最良の):(event, delete, date_created)です。

  • 第三に、次のように書き直してみてください。

最初にLIMIT、次にJOIN(修正済み):

SELECT karmalog.*, image.title as img_title, image.date_uploaded, imagefile.file_name as img_filename, imagefile.width as img_width, imagefile.height as img_height, imagefile.transferred as img_transferred, u1.uname as usr_name1, u2.uname as usr_name2, u1.avat_url as usr_avaturl1, u2.avat_url as usr_avaturl2, class.title as class_title,forum.id as f_id, forum.name as f_name, forum.icon, forumtopic.id as ft_id, forumtopic.subject
FROM 
    ( SELECT *
      FROM karmalog
      WHERE karmalog.event IN ('EDIT_PROFILE','FAV_IMG_ADD','FOLLOW','COM_POST','IMG_UPLOAD','IMG_VOTE','LIST_VOTE','JOIN','CLASS_UP','CLASS_DOWN','LIST_CREATE','FORUM_REPLY','FORUM_CREATE','FORUM_SUBSCRIBE')
        AND karmalog.delete=0
      ORDER BY karmalog.date_created DESC, karmalog.id DESC 
      LIMIT 0,13  
    ) AS karmalog 
LEFT JOIN image on karmalog.event_type = 'image' and karmalog.object_id = image.id 
LEFT JOIN imagefile on karmalog.object_id = imagefile.image_id and imagefile.type = 'smallthumb'
LEFT JOIN class on karmalog.event_type = 'class' and karmalog.object_id = class.num
LEFT JOIN user as u1 on karmalog.user_id = u1.id
LEFT JOIN user as u2 on karmalog.user_sec_id = u2.id
LEFT JOIN forumtopic on karmalog.object_id = forumtopic.id and karmalog.event IN ('FORUM_REPLY','FORUM_CREATE')
LEFT JOIN forum on forumtopic.forum_id = forum.id
ORDER BY karmalog.date_created DESC, karmalog.id DESC 
于 2011-10-21T12:28:16.367 に答える
2

説明の重要な部分は次のとおりです。 possible keys、、keysおよびrows

可能なキーがない場合は、インデックスを作成する必要があります。
キーが使用されていない場合は、次のいずれかが原因である可能性があります。

  • キーのカーディナリティが低い。
  • 関数の使用;

行数が最も多いテーブルに注力してください。すなわちkarmalog

MySQLは、テーブルごとの選択ごとに1つのインデックスしか使用できないことに注意してください。
結合はすべて左結合であるため、インデックスの行数を制限しkarmalogないため、ここでは役に立ちません。パーツ
を見ると、カーディナリティが低くなっています(2つの値のみで、そのうちの90%がになります)。したがって、event + date_createdフィールドのみがインデックスの対象となり、インデックスを次の場所に配置します。wheredeleted=0

ALTER TABLE karmalog ADD INDEX date_event (event, date_created);
于 2011-10-21T12:29:36.603 に答える
1

テーブル karmalog の確実なイベント (delete と object_id など) にインデックスを配置してみてください。これにより高速になり、最初の結合のキーが与えられます。

次にこのテーブルを見て、何らかの結合を使用してこれを実行し、将来軽量化できるかどうかを判断してください。しかし、それはおそらくあなたのデータベースへの変更を意味するでしょう

karmalog.event IN ('EDIT_PROFILE','FAV_IMG_ADD','FOLLOW','COM_POST','IMG_UPLOAD','IMG_VOTE','LIST_VOTE','JOIN','CLASS_UP','CLASS_DOWN','LIST_CREATE','FORUM_REPLY','FORUM_CREATE','FORUM_SUBSCRIBE')
于 2011-10-21T12:26:17.540 に答える