我有这样的感觉:
CREATE TABLE UserTrans (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`transaction_id` varchar(255) NOT NULL default '0',
`source` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`)
)
使用innodb引擎。
transaction_id是var,因为有时它可能是aphanumeric。
id是主键。
所以..这就是事情,我有超过1M的记录。但是,有一个查询要检查指定源上的重复transaciton_id。所以,这是我的问题:
SELECT *
FROM UserTrans
WHERE transaction_id = '212398043'
AND source = 'COMPANY_A';
这个查询变得非常慢,比如现在运行2秒。我应该索引transaction_id和来源吗?
例如KEY join_id
(transaction_id
,source
)
如果我这样做有什么缺点?
答案 0 :(得分:6)
显然,好处是它可以提高某些查询的性能。
缺点是它需要一些空间来存储索引以及RDBMS维护索引的一些工作。索引特别容易占用空间,因为您的transaction_id是一个如此宽的字符串。
您可能会考虑transaction_id是否真的需要最多255个字符,或者您是否可以声明其最大长度更短。
或者您可以使用前缀索引仅索引第一个 n 字符:
CREATE INDEX join_id ON UserTrans (transaction_id(16), source(16));
@Daniel有一个很好的观点,即您可以通过仅索引一列来获得相同的好处并节省更多空间。由于你正在做SELECT *
,你已经排除了覆盖指数的好处。
此外,如果您希望transaction_id是唯一的,为什么不将它限制为唯一?
CREATE UNIQE INDEX uq_transaction_id ON UserTrans (transaction_id(16));
答案 1 :(得分:5)
主要缺点是新索引会占用磁盘空间。它还会使插入和更新变慢(但在大多数情况下这通常可以忽略不计)。
另一方面,您的查询可能只需几毫秒而不是2秒。
答案 2 :(得分:1)
添加索引的缺点是空间(因为存储索引会占用空间)和插入时间(因为当您插入新记录时,必须将它们添加到索引中)。
也就是说,您可能不需要将两个字段编入索引 - 只需将其中一个字段编入索引即可。
答案 3 :(得分:1)
我会想到你的id列,并使用transaction_id作为你的主键 我假设transaction_id是唯一的。
这意味着您的架构会阻止您插入已存在的事务ID。
这减少了存储的数据量,也减少了需要编制索引的列数。
如果source company和transaction_id实际上是一个复合键..我会将这两列作为主键。
您当前的架构允许您放入重复项,这是一种不必要的恶意。