2016-12-31 11 views
0

私はチャットメッセージを保存するこのスキーマを持っています。現在私は、約5.5MBのデータである約100k行を持っています。インデックスのサイズは6.5MBです。データサイズが〜4MBだったとき、インデックスサイズは〜3MBだったので、が指数関数的にになっていますか?テーブルを最適化してインデックスサイズを小さくする

CREATE TABLE `messages` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `author` int(11) unsigned DEFAULT NULL, 
    `time` int(10) unsigned DEFAULT NULL, 
    `text` text, 
    `dest` int(11) unsigned DEFAULT NULL, 
    `type` tinyint(4) unsigned DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `history` (`author`,`dest`,`id`) USING BTREE, 
    KEY `messages_ibfk_1` (`dest`), 
    FULLTEXT KEY `msg` (`text`), 
    CONSTRAINT `au` FOREIGN KEY (`author`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT `messages_ibfk_1` FOREIGN KEY (`dest`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=105895 DEFAULT CHARSET=utf8; 

私は2人

SELECT id, time, text, dest, type, author 
FROM `messages` 
WHERE (
    (author = ? AND dest = ?) OR (author = ? AND dest = ?) 
) AND id <= ? ORDER BY id DESC LIMIT ?, 25 

間のチャットのためのページ分割の履歴を表示する必要がある場合、私は、この表に対して実行されていることだし、私はそれを最適化しようとしたことを主なクエリがありますヒストリの他のクエリは、検索タームまたは日付範囲に追加のフィルタがある以外は同じです。

インデックスサイズを縮小し、最適なパフォーマンスを維持するためにできることはありますか?

+0

なぜインデックスのサイズがパフォーマンスと関係していると思いますか?クエリが遅く実行されていますか?結局のところ、インデックスがない場合は、多くのスペースを節約できますが、クエリが非常に遅くなるので、明らかにインデックスを持つことはスペースパフォーマンスのトレードオフのようなものです。スペースを犠牲にしてパフォーマンスを披露したいと表明しました。 –

+0

将来の挿入を予期して、MySQLがbtreeに未塗り領域を残していると、インデックスがテーブル自体より大きくなることがあります。 –

+0

ところで、 "author"と "dest"の代わりに "user1"と "user2"を格納し、2人のユーザーをアルファベット順に並べ、 "user1"を最初のユーザーにすることで、インデックスのサイズを減らしてクエリのパフォーマンスを向上させることができます。 "user2"は2番目です。 MarkとAliceの会話を探したい場合、Aliceは常に「user1」になり、Markは常に「user2」になります。次に、「user1」が作成者か受信者かを示す別の列を追加できます。 –

答えて

1

インデックスの増加について心配する必要はありません。それはたぶんたぶんです。確かに "指数関数的"ではない。 UNIONLIMITを扱う、UNIONに変更OR、およびページネーションのためのOFFSETを使用していない:主な問題を想定し

は、私が大幅に役立つ3つの手法を参照してください

SELECT id, time, text, dest, type, author 
FROM `messages` 
WHERE (
    (author = ? AND dest = ?) OR (author = ? AND dest = ?) 
) AND id <= ? ORDER BY id DESC LIMIT ?, 25 

のパフォーマンスです。

 (SELECT id, time, text, dest, type, author 
      FROM `messages` 
      WHERE author = ? -- one author & dest 
       AND dest = ? 
       AND id < ? -- where you "left off" 
      ORDER BY id DESC 
      LIMIT 25 
     ) UNION ALL 
     (SELECT id, time, text, dest, type, author 
      FROM `messages` 
      WHERE author = ? -- the other author & dest 
       AND dest = ? 
       AND id < ?  -- same as above 
      ORDER BY id DESC 
      LIMIT 25 
     ) 
     ORDER BY id DESC 
     LIMIT 25;   -- get the desired 25 from the 50 above 

Pagination discussionOFFSETを除去しなければならない理由を説明します。それは25の代わりに26を(3つの場所すべてで)使用することを含む他のテクニックについて議論し、これが最後のページかどうかを知ることができます。

最初の反復では、AND id < ?をオフにすることができます。または(より単純な)、あなたは非常に大きな数を代用することができます。

あなたのインデックス(authordestid)は私の処方に最適です。

messagesが大きくなったり、ユーザーページがリストのさらに遠くになると、この複雑な配合が輝きます。

+0

このフォーミュレーションは、表のサイズやページ番号に関係なく、最大50行(tmpと50の再書き込み)をタッチします。元の処方は、大部分またはすべての行に常に触れました。 –

+0

この回答をお寄せいただきありがとうございます。これは最も参考になりました。特に、ページ区切りにオフセットを使用しないようにすることについて、私は過去にこの問題に遭遇しました。しかし、私のデータよりも大きなインデックスを持つIMH(noob)Oが手に入らないように見えるので、このインデックスのサイズが許容できるかどうか、またそれをどのように減らすかという問題がありました。 –

+0

また、私が指摘した価値があると思ったのは、1msでオフセットリターンなしの質問から元のクエリを実行しても、50msで同じ結果をユニオンで返すということでした。私はテーブルをデザインしていたときにもこれをテストしたことを覚えています。以前はそれが以前と同じでした。「OR」は何度も「UNION」を上回りました。 –

関連する問題