replace into index_tb_companies(
company_id, company_country, company_state)
(select
company_id, company_country, company_state
from original_company_table
where country in ('US', 'CA')
);
select o.*
from
original_company_table o INNER JOIN
index_tb_companies idx ON idx.company_id = o.company_id
where
idx.company_country = 'US'
and idx.company_state = 'NY'
3条答案
按热度按时间qni6mghb1#
创建一个索引需要时间,与表中的行数成正比。对于一个MySQL表来说,1亿行是相当多的。在该表上创建一个索引可能需要许多小时。确切的时间长短取决于其他因素,包括服务器硬件、要为其创建索引的列的数据类型、数据库上的其他当前负载等。
pt-online-schema-change是一个可以帮助你的工具,它实际上需要更长的时间来建立索引,但是你可以在它工作的时候继续读写原始的表,用一个较小的表来测试,这样你就可以获得一些使用这个工具的经验。
您可以在此处查看有关此工具的网络研讨会:Zero-Downtime Schema Changes in MySQL(免费观看,但需要注册)。
另一种方法是创建一个与原始表类似的空表,在该表中创建索引,然后开始逐步将数据从原始表复制到新表中。如果这是一个日志表,则写入表的次数可能多于读取表的次数,因此您可以立即交换表并立即开始记录新事件,然后随着时间的推移对其进行回填。
像pt-archiver这样的工具可以帮助您逐步复制数据,而不会给服务器带来太多的负载。如果您试图在一个事务中复制1亿行,那么简单地执行
INSERT INTO... SELECT
对数据库服务器的健康没有好处。它还会在原始表上设置锁。pt-archiver的工作原理是一次只复制一小块行。因此它避免了如此大的交易的高成本。如果使用自动递增主键,请在日志事件开始写入表之前,注意将值调整为高于原始表中的最大值,这样就不会意外地多次标识值。
6gpjuf902#
用途
然后在NewTable为空时将索引应用到NewTable。
然后
这也可能需要很长时间才能完成。
xxslljrj3#
虫子
在使用MyISAM引擎的MySQL表上创建新的辅助索引时会出现一些问题。
MyISAM引擎的一个已知问题是,在一些MySQL版本,如5.7.24(例如Wamp)上,不仅会导致表扫描,而且在创建索引时需要重建整个表。如果您只是删除索引,表也会重建:-(
参考:https://bugs.mysql.com/bug.php?id=93530
备选
有时你不能升级MySQL或者不能要求客户这样做来运行你的解决方案。如果你不需要InnoDB提供的所有功能,将引擎更改为InnoDB可能会导致另一个问题。
索引表
因此,有一种方法是手动创建一个"索引表",这样做的好处是您可以过滤真正需要的记录,正如我在下面解释的:
想象一下,你有一个表上的世界公司的100M记录,其中约30M是美国公司和10M来自加拿大,加上其他公司。
每个公司都有一个COUNTRY和一个STATE字段,您需要对其进行索引,因为您需要按其所在的州搜索美国或加拿大公司。
因此,在MySQL中,如果为Country和State创建索引,那么所有1亿条记录都会被索引,即使是NULL状态。
要解决这个问题,你创建一个索引表和一个真正的索引,如下所示:
填充索引表
现在您可以使用简单的
insert into
或带有过滤后的select
的replace into
将原始数据导入索引表。这将需要一段时间,因为你可能还没有国家的索引,需要一个完整的表扫描。但最终的索引表大小将低于MySQL索引大小,因为只有美国/加拿大的数据将在那里。
如何选择
现在,最后一部分是利用索引表与您的具体报告的美国和CA公司,因为其他国家不包括在该指数。
当您希望索引MySQL上的一小部分数据时,这种方法特别好,因为索引大小很小。
部分索引
其他数据库,如PostgreSQL,有一个"部分索引",你可以创建常规索引,并在创建时传递一个
where
子句。PG部分索引:https://www.postgresql.org/docs/8.0/indexes-partial.html
喜欢并分享这个解决方案,如果你从中学习,我正在制作一些关于数据库的材料,并感谢反馈。