Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 包含8000万条记录和添加索引的表需要超过18小时(或永远)!现在怎么办?_Mysql_Database_Database Design_Partitioning - Fatal编程技术网

Mysql 包含8000万条记录和添加索引的表需要超过18小时(或永远)!现在怎么办?

Mysql 包含8000万条记录和添加索引的表需要超过18小时(或永远)!现在怎么办?,mysql,database,database-design,partitioning,Mysql,Database,Database Design,Partitioning,对所发生事情的简短回顾。我正在处理7100万条记录(与其他人处理的数十亿条记录相比,这并不算多)。另一方面,有人建议我的集群的当前设置不适合我的需要。我的表格结构是: CREATE TABLE `IPAddresses` ( `id` int(11) unsigned NOT NULL auto_increment, `ipaddress` bigint(20) unsigned default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM;

对所发生事情的简短回顾。我正在处理7100万条记录(与其他人处理的数十亿条记录相比,这并不算多)。另一方面,有人建议我的集群的当前设置不适合我的需要。我的表格结构是:

CREATE TABLE `IPAddresses` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `ipaddress` bigint(20) unsigned default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM;
我添加了7100万条记录,然后做了一个:

ALTER TABLE IPAddresses ADD INDEX(ipaddress);

已经14个小时了,手术还没有完成。通过谷歌搜索,我发现有一种解决这个问题的众所周知的方法——分区。我知道我现在需要根据ipaddress对表进行分区,但是我可以在不重新创建整个表的情况下进行分区吗?我是说,通过另一种说法?如果是,则有一个要求是要分区的列应该是主键。我将使用此ipaddress的id构造另一个表,以便ipaddress不是我的主键。在这种情况下,如何对表进行分区?

确定结果表明,这个问题不仅仅是一个简单的创建表、索引和忘记问题:)以下是我为防止其他人面临相同问题而做的操作(我使用了一个IP地址示例,但它也适用于其他数据类型):

问题:您的表有数百万个条目,您需要快速添加索引

<强> uCase:<强>考虑在查找表中存储数百万个IP地址。添加IP地址应该不是一个大问题,但在其上创建索引需要14个多小时

解决方案:使用g策略对表进行分区

案例#1:您想要的表格尚未创建时

CREATE TABLE IPADDRESSES(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  ipaddress BIGINT UNSIGNED,
  PRIMARY KEY(id, ipaddress)
) ENGINE=MYISAM
PARTITION BY HASH(ipaddress)
PARTITIONS 20;
Case#2:当您想要的表已经创建时。 似乎有一种方法可以使用ALTERTABLE来实现这一点,但我还没有找到合适的解决方案。相反,有一个稍微低效的解决方案:

CREATE TABLE IPADDRESSES_TEMP(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  ipaddress BIGINT UNSIGNED,
  PRIMARY KEY(id)
) ENGINE=MYISAM;
在此表中插入您的IP地址。然后创建带有分区的实际表:

CREATE TABLE IPADDRESSES(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  ipaddress BIGINT UNSIGNED,
  PRIMARY KEY(id, ipaddress)
) ENGINE=MYISAM
PARTITION BY HASH(ipaddress)
PARTITIONS 20;
最后

INSERT INTO IPADDRESSES(ipaddress) SELECT ipaddress FROM IPADDRESSES_TEMP;
DROP TABLE IPADDRESSES_TEMP;
ALTER TABLE IPADDRESSES ADD INDEX(ipaddress)

你就这样。。。在一台3.2GHz、内存为1GB的机器上对新表进行索引花费了我大约2个小时:)希望这会有所帮助。

您正在使用MyISAM,它很快就会被弃用。另一种选择是InnoDB

“InnoDB是用于MySQL的事务安全(符合ACID)存储引擎,具有提交、回滚和崩溃恢复功能以保护用户数据。InnoDB行级锁定(无需升级为粗粒度锁)Oracle风格的一致性非锁定读取提高了多用户并发性和性能。InnoDB将用户数据存储在聚集索引中,以减少基于主键的常见查询的I/O。为了保持数据完整性,InnoDB还支持外键引用完整性约束。您可以将InnoDB表与来自其他MySQL存储引擎,甚至在同一语句中。”\

根据:


,您应该能够通过使用一个简单的alter命令在不同的引擎之间切换,该命令允许您具有一定的灵活性。它还指出,数据库中的每个表都可以独立配置。

使用MySQL创建索引很慢,但没有那么慢。有7100万条记录,应该需要几分钟,而不是14小时。可能出现的问题有:

  • 您尚未配置排序缓冲区大小和其他配置选项
看这里:

如果您尝试使用8MB排序缓冲区生成1GB索引,则需要大量的过程。但是,如果缓冲区大于CPU缓存,它会变慢。所以你必须测试,看看什么最有效

  • 有人在桌子上有一把锁
  • 你的IO系统糟透了
  • 您的服务器正在交换
像往常一样,检查iostat、vmstat、日志等。在您的表上发出一个锁表,以检查是否有人在上面有锁


仅供参考,在我的64位桌面上创建10M随机大整数的索引需要17秒…

在您的表中。您已经插入了710亿条记录。现在,如果要在表的主键列上创建分区,可以使用ALTERTABLE选项。文中举了一个例子供大家参考

CREATE TABLE t1 (
    id INT,
    year_col INT
);

ALTER TABLE t1
    PARTITION BY HASH(id)
    PARTITIONS 8;

我遇到了一个问题,我想通过添加索引来加快查询速度。该表只有大约30万条记录,但也花了太长时间。当我检查mysql服务器进程时,发现我试图优化的查询仍然在后台运行。4次!在我消除了这些查询之后,索引很快就完成了。也许同样的问题也适用于您的情况。

MySQL自己的分区文档:id字段完全不必要。@Seun:在这种情况下,如果我想构建一个包含(比如)URI | ipaddress的表,并想使用与ipaddress关联的id,我该如何做?我试图规范化一个不同的表,它首先需要创建这个表。有什么建议吗?ip地址可以作为自己的密钥。您可以用单个整数表示Ipv4地址,如:创建表IPAddresses(ipaddress int unsigned primary key)ENGINE=MyISAM;谢谢你的指点。然而,我目前正在寻找一个MyISAM特定的解决方案,尽管我将准备一个计划,以便随后迁移到InnoDB;kill[query | connection]{process_id};