我有一个表,其中包含多个租户的数据。
CREATE TABLE `accountPost` (
`id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
`tenantId` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '',
`accountId` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`scheduledTime` BIGINT(19),
......more columns
PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=781625 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
这里,scheduledTime 是时间戳。 tenantId 对于许多 accountPost 行来说是常见的。
现在,我有一个类似的查询
select * from accountPost
where scheduledTime > t1
and scheduledTime < t2
and tenantId = "x";
对于这个查询,我想创建一个复合索引。
1. ALTER TABLE `accountPost` ADD INDEX `idx1` (`scheduledTime`, `tenantId`);
2. ALTER TABLE `accountPost` ADD INDEX `idx1` (`tenantId`, `scheduledTime`);
我应该使用这两者中的哪一个来获得插入和读取的最佳性能,为什么? 是否应该将更频繁的列添加为复合索引中的第一个列?
最佳答案
综合指数的各个组成部分的基数是无关紧要的。
重要的是输入 =
<
之前的列(等)列。所以这必然是更好的顺序:
INDEX(`tenantId`, `scheduledTime`)
(同时,WHERE
中子句的顺序并不重要。)
至于读与写... SELECT
良好索引的好处远远超过写入(插入/更新/删除)的微小开销。添加读取所需的所有索引;丢弃任何冗余或从未使用过的索引。那么不用担心。
比较日期(或日期时间)的提示:谨防 BETWEEN
或者,在您的示例中,<
和>
-- 它们包含或排除两个端点。我喜欢以下模式:
WHERE dt >= '2019-12-27'
AND dt < '2019-12-27' + INTERVAL 7 DAY
模式提示:考虑使用较小的数据类型。 255
很方便,但有一些小的性能问题。 BIGINT
(8 字节)几乎总是比需要的大。大小对于磁盘空间和缓存很重要。
你从哪里得到的BIGDECIMAL
??
关于mysql - 如果一列非常频繁,则mysql中的复合索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59633161/