Mysql 在bigtable 800'000'000行MariaDB InnoDB上搜索1行数据

Mysql 在bigtable 800'000'000行MariaDB InnoDB上搜索1行数据,mysql,mariadb,innodb,bigdata,Mysql,Mariadb,Innodb,Bigdata,我有一张储存电话号码的桌子,有800M行 column region_code_id smallint(4) unsigned YES local_number mediumint(7) unsigned YES region_id smallint(4) unsigned YES operator_id smallint(4) unsigned YES id int(10

我有一张储存电话号码的桌子,有800M行

column
region_code_id  smallint(4)  unsigned   YES         
local_number    mediumint(7) unsigned   YES         
region_id       smallint(4)  unsigned   YES         
operator_id     smallint(4)  unsigned   YES         
id  int(10)     unsigned     NO PRI     auto_increment
我需要找到number.id,其中region\u code\u id=119和localnumber=1234567

此查询执行时间超过600秒。 我怎样才能改进它

更新

感谢unswer,我知道我需要本专栏的索引,我会在得到更多SSD的服务器后立即尝试,现在我有了1GB的可用SSD空间。如何确定索引将占用多少空间?

对于此查询:

select *
from numbers
where numbers.region_code_id = 119 and
      numbers.local_number = 1234567;
您需要一个关于numbersregion\u code\u id、local\u number或numberslocal\u number、region\u code\u id的索引。列的顺序无关紧要,因为两列的条件相等

create index idx_numbers_region_local on numbers(region_code_id, local_number);
考虑在WHERE子句中使用的列上添加索引

首先:

ALTER TABLE `numbers`
    ADD INDEX `region_code_id_local_number` 
    (`region_code_id`, `local_number`);
注意:建立索引可能需要一些时间

变更前后,执行解释计划进行比较:

EXPLAIN EXTENDED select * from numbers where numbers.region_code_id = 119 and numbers.local_number = 1234567;
参考资料:

我同意INDEXregion\u code\u id、local\u number(按任意顺序排列)对于这个问题都是强制性的,但我正在埋头进一步研究。那对不是独一无二的吗?或者表中是否有重复的数字?如果它是唯一的,那么去掉id,并使该对成为主键区域\代码\ id,本地\编号。更改后,表格可能会变小

回到你的问题,多大。这张桌子现在有多大?也许是40GB?最初提出的二级索引可能会增加大约20GB。您需要20-60GB的可用磁盘空间来执行更改。这取决于是否可以在该版本中就地添加索引

按照我的建议更改PK将导致表的容量略低于40GB。执行更改需要40GB的可用空间

通常,悲观地说,计划一个ALTER,同时需要原始表和磁盘上的新表。这包括数据和索引的完整副本

一个附带问题:您确定本地_号码在任何地方都限制为7位吗

另一种解决问题的方法。。。要计算InnoDB中表或索引的大小,请将MEDIUMINT的数据类型大小加上3字节,VARCHAR的一些平均值,等等,然后乘以行数。然后乘以4;这将为您提供所需的大致磁盘空间。通常2-3对于最后一个乘法器就足够了

更改主键时,一步完成:

ALTER TABLE foo
    DROP PRIMARY KEY,
    ADD  PRIMARY KEY(region_code_id, local_number);
更改PK不能就地完成

主要为其他读者编辑

@berap指出,id用于其他目的。因此,删除id和切换PK不是一个选项

然而,这有时是一种选择,在这种情况下可能不是:

ALTER TABLE foo
    DROP PRIMARY KEY,
    ADD  PRIMARY KEY(region_code_id, local_number),
    ADD  INDEX(id);
注:

即使仅使用索引,id..AUTO_增量也将继续工作。 问题中的SELECT将更有效,因为它是PK。 选择其中id=。。。将降低效率,因为id是辅助密钥。 无论哪种方式,表的大小都相同;无论哪种方式,次键的大小都是相同的——因为每个次键也包含PK列。此注释是针对InnoDB的。
您是否有区域代码id、本地编号的索引?您是否在索引列上搜索?表有多大?它是否能够放入内存以更快地搜索?数据库的服务器设置是什么?它运行在什么样的硬件上?谢谢,我以前尝试过这个,只要我得到更多SSD的服务器,现在我有了1GB的SSD空间。我如何才能知道索引将占用多少空间?现在我有了id列的索引。如果不需要id,我可以删除它吗?我不会删除主键。对数据库进行转储/备份,并在扩大可用磁盘空间后重新导入。您好,感谢您的回答。对“区域代码id”,“本地编号”是唯一的,但我有一个表“编号注释”,其中注释由“编号.id”关联。我又加了一些东西。继续添加INDEXregion\u code\u id和local\u number作为最佳选项。
ALTER TABLE foo
    DROP PRIMARY KEY,
    ADD  PRIMARY KEY(region_code_id, local_number),
    ADD  INDEX(id);