处理巨大的MyISAM表以进行优化

时间:2017-01-30 18:12:17

标签: mysql database optimization partitioning myisam

我有一个巨大的(并且正在增长的)MyISAM表(700万行= 140Gb)。

CREATE TABLE `keypairs` (
  `ID` char(60) NOT NULL,
  `pair` char(60) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=MyISAM

表格选项已更改为ROW_FORMAT=FIXED,因为两列的长度始终固定为最大值(60)。是的,ID很遗憾,而不是INT。

SELECT查询速度效率非常好。

数据库和mysql引擎都是127.0.0.1/localhost。 (没什么遥远的)

可悲的是,INSERT很慢。我甚至没有谈到尝试LOAD DATA数百万个新行......需要几天时间。

不会有任何并发​​读取。所有SELECT都是由我的本地服务器逐个完成的(不是供客户使用)

(适用于信息:文件大小.MYD = 88Gb,.MYI = 53Gb,.TMM = 400Mb)

  • 我怎样才能加速插入该表?
  • 那个庞大的桌子对PARTITION有帮助吗? (那怎么办?)
  • 我听说MyISAM使用“结构缓存”作为.frm文件。并且配置文件中的一行是帮助mysql将所有.frm保存在内存中(在分区的情况下),它是否也有帮助? Actualy,我的.frm文件只有7亿,只有7亿行)
  • 字符串缩短/压缩功能... ID字符串? (与彩虹表相同的想法)即使它降低了最大允许的唯一ID,我仍然永远不会达到60chars的最大值。也许这是一个想法?但在创建新的唯一ID之前,我必须检查db ofc中是否存在缩短的字符串
  • 与缩短ID字符串相同的想法,如何在ID上使用md5()?在这种情况下,缩短字符串意味着更快还是没有?

3 个答案:

答案 0 :(得分:2)

  • 在执行LOAD之前对传入数据进行排序。这将提高PRIMARY KEY(id)
  • 的可缓存性
  • PARTITIONing不太可能有所帮助,除非ID有一些有用的模式。
  • PARTITIONing帮助进行单行插入,也不会ID进行单行抓取。
  • 如果字符串的常量宽度不是60,则说明CHAR而不是VARCHAR会浪费空间和速度。改变它。
  • MyISAM FIXED只有在有很多“流失”的情况下才有用。 (删除+插入和/或更新)。
  • 较小意味着更多可缓存意味着更少的I / O意味着更快。
  • .frmCREATE TABLE的编码;这与此讨论无关。
  • 一个简单的压缩/ zip /几乎总是压缩超过10个字符的 text 字符串。它们可以无损地解压缩。你的字符串是什么样的? 60个字符的英文文本将缩小为20-25个字节。
  • MD5是一个"摘要"而不是"压缩"。您无法从其MD5恢复字符串。无论如何,转换为BINARY(16)后需要16个字节。
  • PRIMARY KEY是BTree。如果ID有点"随机",那么' next' ID(除非输入已排序)可能不会被缓存。不,BTree 一直重新平衡。
  • PRIMARY KEY转换为辅助密钥(在添加AUTO_INCREMENT之后)将加快速度 - 它仍然需要使用{{1}更新BTree在它!
  • 你有多少内存?对于您的情况和此LOAD ,请将MyISAM的ID设置为大约70%的可用内存,但不大于{{1文件。我推荐一个大的key_buffer,因为那是随机访问的发生地; key_buffer_size仅被附加到(假设您从未删除任何行)。
  • 我们确实需要查看您的.MYI,以确保这些更改不会破坏其他地方的效果。
  • 确保您使用的是.MYD latin1或ascii; utf8会使用SELECTs浪费更多空间。

切换到InnoDB会使表的磁盘空间(数据+索引)增加一倍,可能增加三倍。因此,它可能会显示下来。但是一个缓解因素是PK已经集群化了#34;使用数据,因此您不会为插入的每一行更新两件事。请注意,CHARACTER SET应降至10M,CHAR应设置为可用内存的70%。

(我的子弹项目适用于InnoDB,除非指定了MyISAM。)

在使用InnoDB时,尝试每个事务插入1000行会很好。少于此会导致更多的交易开销;超过这导致超越撤消日志,导致不同形式的减速。

十六进制ID

由于key_buffer_size始终为60个十六进制数字,因此请将其声明为innodb_buffer_pool_size并通过ID打包并通过BINARY(30)获取。通过UNHEX(...)进行测试。这将使数据缩小约25%,而MyISAM的PK缩小约40%。 (InnoDB总体上为25%。)

转换为HEX(ID)

WHERE ID = UNHEX(...)

微小内存

只有2GB的RAM,仅MyISAM数据集应使用BINARY(30)CREATE TABLE new ( ID BINARY(30) NOT NULL, `pair` char(60) NOT NULL -- adding the PK later is faster for MyISAM ) ENGINE=MyISAM; INSERT INTO new SELECT UNHEX(ID), pair FROM keypairs; ALTER TABLE keypairs ADD PRIMARY KEY (`ID`); -- For InnoDB, I would do differently RENAME TABLE keypairs TO old, new TO keypairs; DROP TABLE old; 之类的内容。仅适用于InnoDB:key_buffer_size=300Minnodb_buffer_pool_size=0。由于key_buffer_size=10M可能是某种摘要,因此非常随机。小缓存和随机密钥组合起来意味着几乎每个插入都涉及磁盘I / O.我的第一次估计更像是插入10M行30个小时。你有什么样的驱动器?如果您还没有固态硬盘,那么固态硬盘会有很大的不同。

加快innodb_buffer_pool_size=500M的另一件事是在启动ID之前按INSERTs 排序。但是ID会变得棘手。这就是我推荐的内容。

  1. 使用LOADUNHEX创建 MyISAM tmp,但索引。 (不要担心ID BINARY(30);它不会被使用。)
  2. pair将数据导入key_buffer_size
  3. LOAD这将对表格进行排序。仍然没有索引。我认为,如果没有证据,这将是一个文件分区,通过密钥缓冲区"修复更快。对于这种情况。
  4. tmp这会通过按ALTER TABLE tmp ORDER BY ID;顺序将行提供到INSERT INTO keypairs SELECT * FROM tmp;来最大化缓存。
  5. 同样,我已经仔细拼写了一些内容,以便无论哪个引擎keypairs都适用,它都能正常运行。我希望步骤3或4花费的时间最长,但我不知道哪一个。

答案 1 :(得分:0)

优化表格需要针对特定​​查询进行优化。除非您考虑到特定的问题,否则无法确定最佳优化策略。任何优化都会以牺牲其他类型的查询为代价来改进一种类型的查询。

例如,如果您的查询是SELECT SUM(pair) FROM keypairs(无论如何都必须扫描整个表格的查询),分区不会有帮助,只会增加开销。

如果我们假设您的典型查询是通过其主键一次插入或选择一个密钥对,那么是的,分区可以帮助很多。这完全取决于优化器是否可以告诉您的查询将在一个狭窄的分区子集中找到它的数据(理想情况下是一个分区)。

还要确保调整MyISAM。没有很多调整选项:

  • 尽可能高地分配key_buffer_size以缓存索引。虽然我没有尝试过高于10GB的任何东西,但我无法保证MyISAM密钥缓冲区稳定在53GB(MYI文件的大小)。
  • 预加载密钥缓冲区:https://dev.mysql.com/doc/refman/5.7/en/cache-index.html
  • 根据您运行的查询,适当地调整read_buffer_sizeread_rnd_buffer_size。我无法在此处提供特定值,您应该使用查询测试不同的值。
  • 如果您想加快LOAD DATA INFILE的速度,请将bulk_insert_buffer_size大小调整为大小。它默认为8MB,我尝试至少256MB。我没有尝试过这种设置,所以我无法从经验中说话。

我尽量不使用MyISAM。 MySQL绝对试图弃用它。

  

...是否有自动命令ALTER TABLE添加INT ID增量列?

是的,请参阅我对https://stackoverflow.com/a/251630/20860

的回答

答案 2 :(得分:-1)

首先,您的主键不可递增。 这意味着,粗略地说:在每次插入时,索引都必须重新平衡。

难怪它在这么大的桌子上慢慢走。 而这样的引擎......

所以,对于第二个问题:保持MyISAM旧垃圾的重点是什么?

例如,在发生事故时,你不介意放松一两行(或十几岁)吗?等等,甚至抛弃当前的MySQL维护者(Oracle Corp)明确不鼓励使用MyISAM。

所以,这里有可能的解决方案:

1)切换到Inno;

2)如果你不能放弃char ID,那么:

  • 添加自动增量数字键并将其设置为主数据 - 然后,将聚集索引并且插入成本会显着下降;

  • 将当前密钥转换为二级索引;

3)如果你能 - 它很明显