草庐IT

mysql - 编辑-MySQL。大型 MyISAM 表(4000 万条记录)的索引速度非常慢且磁盘上的大小很大

coder 2023-10-14 原文

该表包含大约 40,000,000 条记录:

CREATE TABLE `event` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `some_other_id_not_fk` int(10) unsigned default NOT NULL,
  `event_time` datetime NOT NULL,
  `radius` float default NULL,
  `how_heavy` smallint(6) default NULL,
  PRIMARY KEY  (`id`),
  KEY `event_some_other_id_not_fk` (`some_other_id_not_fk`),
  KEY `event_event_time` (`event_time`)
) ENGINE=MyISAM AUTO_INCREMENT=6506226 DEFAULT CHARSET=utf8 

您应该知道 some_other_id_not_fk 列并不大,它只包含 7 个不同的数字。真正的痛苦是 event_time 日期时间列,因为它包含大量不同的日期时间,并且基本上所有内容都是允许的:重复以及无法预测的大时间间隔,没有记录来“覆盖”它们。您还应该知道 (some_other_id_not_fk,event_time) 对必须允许重复 :( 我知道这会导致更多问题 :(

我在优化MySQL表方面有过一些经验,但从未出现过如此巨大的痛苦:/

“事物”的当前状态是:

  • event_time 在 date1 和 date2 之间进行的选择(我需要这样做)速度非常快。 :)
  • 我的插入速度很慢,我是说真的很慢!!!超过 30 秒,甚至更糟:临时禁用和启用键的加载数据过程非常慢(几个小时),主要是启用键操作。
  • 磁盘上索引的大小是数据大小的 7 倍

到目前为止,我会尝试几种不同的重建索引组合,但数据的大小确实阻止了我随意对索引和列进行删除/创建实验。

请帮助任何人管理过这个?应该使用时间戳而不是日期时间来解决我的问题吗?或者我应该为 dayyear 等添加额外的列并在它们上建立索引?

最佳答案

`id` bigint(20) unsigned NOT NULL auto_increment,

您真的需要 BIGINT 吗?您可能可以摆脱 INT。如果您每天 24 小时每秒插入 1,000 行,则需要 136 年才能用完无符号 32 位整数中的所有值。

此更改将使 4000 万行的表大小减少 152.5 MB,并将 4000 万行的主键索引大小减少 158.8 MB。

`some_other_id_not_fk` int(10) unsigned default NOT NULL,

您声明它只有 7 个不同的值。那么它是否需要是 INT 类型?您可以改用 TINYINT 吗?这将大大减少索引大小。

这会将 4000 万行的表大小减少 114.4 MB,并将 some_other_id_not_fk 索引的大小减少大约相同。

`event_time` datetime NOT NULL,

您需要 DATETIME 吗? DATETIME 占用 8 个字节,一个 TIMESTAMP 占用 4 个字节。如果您可以使用 TIMESTAMP,那么这将大大减少数据和索引大小。请注意 TIMESTAMP 字段的限制,例如 Y2K38以及它们在时区和复制方面的表现。

此更改将使 4000 万行的表大小减少 152.5 MB,并将 4000 万行的主键索引大小减少 158.8 MB。

这三项更改将显着减少数据和索引的大小。

总空间节省

  • 表格:152.5 + 152.5 + 114.4 = 419.4 MB
  • 索引:158.8 + 158.8 + ~115 = 432.6 MB

总计:852MB

正如其他人所建议的,您甚至可能不需要您定义的所有索引。由于 some_other_id_not_fk 的选择性如此之低,查询优化器很可能甚至不会使用该索引,而是选择全表扫描。完全删除此索引将为您的索引节省大量空间。

如果您可以提供一些示例查询,我可以进一步帮助您。

此外,您是否在读取负载很重的情况下向该表中插入数据?请记住,MyISAM 中的 SELECT 会阻止 INSERT。

更新

大多数人建议将您的 some_other_id_not_fk 字段移动到 event_time 索引中,这样新索引就会在 (event_time, some_other_id_not_fk) 上。我会推荐相同的,但有一个重要的警告。

此索引适用于仅在 event_time 上过滤的查询,或者如果您在 event_timesome_other_id_not_fk 上过滤的查询。它不会用于仅在 some_other_id_not_fk 上过滤的查询 - 将进行全表扫描。

此外,如果您的查询总是过滤两者 event_timesome_other_id_not_fk 那么不要 使用 (event_time, some_other_id_not_fk) 的索引顺序。相反,您应该使用索引 (some_other_id_not_fk, event_time) 代替。

优先选择最少(重复次数最多)的字段将允许对索引进行更大程度的压缩,从而显着减少磁盘占用空间。

关于mysql - 编辑-MySQL。大型 MyISAM 表(4000 万条记录)的索引速度非常慢且磁盘上的大小很大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2209030/

有关mysql - 编辑-MySQL。大型 MyISAM 表(4000 万条记录)的索引速度非常慢且磁盘上的大小很大的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  3. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  4. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  5. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  6. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  7. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  8. HBase Region 简介和建议数量&大小 - 2

    Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile

  9. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  10. ruby-on-rails - Ruby - 如何从 ruby​​ 上的 .pfx 文件中提取公钥、rsa 私钥和 CA key - 2

    我有一个.pfx格式的证书,我需要使用ruby​​提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o

随机推荐