虫子
在使用 MyISAM 引擎的 MySQL 表上创建新二级索引时存在一些问题。
MyISAM 引擎的一个已知问题,在某些 MySQL 版本(例如 5.7.24(例如 Wamp 附带)上)不仅会按预期导致表扫描,而且在创建索引时需要重建全表。如果你只是删除一个索引,表也会被重建:-(
参考:https://bugs.mysql.com/bug.php?id=93530
另类
有时您无法升级 MySQL 或无法要求客户这样做,以运行您的解决方案。如果您不需要 InnoDB 提供的所有功能,将引擎更改为 InnoDB 可能会导致另一个问题。
索引表
因此,有一种方法包括手动创建“索引表”,其好处是您可以过滤您真正需要的记录,如下所述:
假设您在一张桌子上有 1 亿条世界公司的记录,其中大约 3000 万条是美国公司,1000 万条来自加拿大,以及其他公司。
每家公司都有一个 COUNTRY 和一个 STATE 字段,您要对其进行索引,因为您需要按其所在州搜索 USA 或 CANADA 公司。
因此,在 MySQL 中,如果您为 Country 和 State 创建索引,则所有 100M 记录都将被索引,即使是 NULL 状态。
要解决这个问题,您需要创建一个索引表和一个真实索引,如下所示:
create table index_tb_companies (
company_id int unique,
company_country char(2), -- US/CA
company_state char(2) -- AL/AK/.../WI/WY
);
create index index_tb_companies_index
on index_tb_companies (company_country, company_state);
填写索引表
现在您可以使用简单的insert into 或replace into 和过滤的select 将原始数据导入索引表。
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')
);
这需要一段时间,因为您可能还没有国家/地区的索引,需要进行全表扫描。但最终的索引表大小将低于 MySQL 索引大小,因为只有 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'
当您想在 MySQL 上索引一小部分数据时,这种方法特别好,因此索引大小很小。
部分索引
其他数据库,如 PostgreSQL,有一个“部分索引”,您可以创建常规索引并在创建时传递 where 子句。
PG 部分索引:https://www.postgresql.org/docs/8.0/indexes-partial.html
如果您从中学习到此解决方案,请点赞并分享,我正在制作一些有关数据库的材料并感谢您的反馈。