优化表以减少索引大小

时间:2016-12-31 02:19:07

标签: mysql indexing data-modeling

我有这个模式可以保存聊天消息。目前我有大约100k行,大约是5.5MB的数据。索引大小为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

历史记录的其他查询相同,只是它们具有针对搜索字词或日期范围的其他过滤器。

有什么办法可以减少索引大小并保持最佳性能吗?

1 个答案:

答案 0 :(得分:1)

不要担心指数的增长。这可能是一个侥幸;当然不是&#34;指数&#34;。

假设主要问题是

的表现
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

我发现有三种技术可以显着提升:将OR更改为UNION,处理LIMIT中的UNION,并且不要使用OFFSET分页。

        ( 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 discussion解释了为什么应删除OFFSET。它讨论了其他技术,包括使用26(在所有三个地方)而不是25,以便你知道这是否是最后一个&#39;页。

在第一次迭代中,AND id < ?可以不用了。或者(更简单),你可以替换一个非常大的数字。

您的索引(authordestid)是我制作的最佳选择。

messages越来越大和/或用户页面越过列表时,这个复杂的公式将会闪耀。