【发布时间】:2017-01-01 06:34:54
【问题描述】:
我有这个保存聊天消息的架构。目前我有大约 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
历史记录的其他查询是相同的,只是它们具有针对搜索词或日期范围的附加过滤器。
有什么办法可以减少索引大小并保持最佳性能?
【问题讨论】:
-
为什么您认为索引大小与性能有关?您的查询运行缓慢吗?毕竟,如果你没有索引,那么你会节省很多空间,但是你的查询会慢很多,所以很明显有一个索引是一种空间性能的权衡,并且通过有索引,你'已经表达了以牺牲空间为代价获得性能的愿望。
-
如果 MySQL 在 btree 中留下一些未填充的空间以预期将来的插入,则您的索引可能大于表本身。
-
顺便说一下,您可以通过存储“user1”和“user2”而不是“author”和“dest”来减小索引的大小并提高查询性能,按字母顺序排列两个用户,并制作“user1”是第一个用户,“user2”是第二个用户。因此,如果您想查找 Mark 和 Alice 之间的对话,Alice 将始终是“user1”,而 Mark 将始终是“user2”。然后您可以添加另一列来指示“user1”是作者还是收件人。
-
@WillisBlackburn 回应您的第一条评论 - 我同意,但是当我的指数变得大于我的实际数据时,这对我来说似乎有点关闭。 2 - 有什么办法可以证实这一点,目前索引比数据大 1.3MB。 3 - 我看不出列名和索引大小之间有什么相关性,我的用户也被存储为整数,不确定你的意思。
-
我不认为你的索引比你的数据大。您看到的 5.5MB 可能不包括“文本”列的大小,因为文本列与主表数据分开存储。毕竟,如果您有 100K 条消息,而它们总共只占用 5.5MB,包括 ID、作者、收件人、日期等所有元数据,那么它们必须是非常短的消息。
标签: mysql indexing data-modeling