草庐IT

mysql - MySQL中如何优化大表,什么时候可以从分区中受益?

coder 2023-10-05 原文

总之,日期范围分区和内存配置实现了我的目标。

我需要增加分配给 的内存innodb_buffer_pool_size 因为默认的 8M 太低了。瑞克詹姆斯推荐 70% of RAM对于这个设置,他有很多很好的信息。

Edlerd 对这两个建议都是正确的:-)

我将数据拆分为每月分区,然后运行 ​​6,000 行响应查询,该查询最初需要 6 到 12 秒。现在它可以在不到一秒的时间内完成 (.984/.031)。我使用默认的 innodb 缓冲区大小(innodb_buffer_pool_size = 8M)运行它以确保它不仅仅是内存增加。

然后我设置 innodb_buffer_pool_size = 4G 并以 0.062/.032 的更好响应运行查询。

我还想提一下,增加内存还提高了我的 Web 应用程序和服务的整体速度,这些应用程序和服务接收消息并将消息写入此表,我对这个配置设置产生的差异感到震惊。我的 Web 服务器的第一个字节时间 (TTFB) 现在几乎与 MySQL Workbench 相当,有时会达到 20 秒。

我还发现slow query log file是一个很好的识别问题的工具,在那里我看到它表明我的 innodb_buffer_pool_size 很低,并突出显示了所有性能不佳的查询。这也确定了我需要索引其他表的区域。

编辑 2016-11-12 解决方案

我正在重构一个记录遥测数据的大表,它已经运行了大约 4-5 个月,并且已经生成了大约平均行大小约为 5400 万条记录。 380 字节。

我已经开始看到我的一个原始数据查询出现一些性能滞后,该查询返回设备在 24 小时内的所有日志。

一开始以为是索引,但我认为是MySQL需要处理的I/O量。典型的 24 小时查询将包含 2.2k 3k 到 9k 记录,我实际上希望支持大约 7 天的导出。

我在数据库性能调优方面没有经验,所以仍然只是学习绳索。我正在考虑一些策略。

  • 根据对原始数据的查询调整复合索引,尽管我认为我的索引没问题,因为解释计划显示了 100% 的命中率。
  • 考虑创建一个覆盖索引以包含所有需要的行
  • 按日期实现范围分区:
    a) 保持每月分区。例如。过去 6 个月
    b) 将任何较旧的内容移至存档表。
  • 使用原始数据创建一个单独的表(垂直分区)并将其与主查询表的 ID 连接。不确定这是我的问题,因为我的索引正在工作。
  • 将我的查询更改为有限制的批量提取数据,然后按创建日期限制 X 排序并继续,直到没有更多记录返回。
  • 查看服务器配置

  • 1,2(索引):
    我会用我的查询重新处理我的索引,但我认为我在这里很好,因为解释显示 100% 命中,除非我读错了。

    我会在重建时尝试覆盖索引,但如何确定设置错误的影响?例如。插入速度受到影响。

    我将如何最好地监控我的表在实时环境中的性能?

    编辑:我刚刚开始使用 slow log file这看起来是一个查找问题的好工具,我想在 performance_schema 上进行查询可能是另一种选择?

    3(分区):
    我已经阅读了一些关于分区的内容,但不确定我的数据大小是否会有很大的不同。

    Rick James suggests > 1M 记录,我有 54M 并且希望在存档前保留大约 300M,我的表是否复杂到足以受益?

    我必须自己测试一下,因为我没有任何这些东西的经验,而且对我来说都是理论性的。如果它不适合我的需要,我只是不想走这条路。

    4(通过‘joined’明细表进行垂直分区):我不认为有表扫描问题,我需要所有行,所以我不确定这种技术是否有用。

    5(使用限制并再次获取):如果我在单个请求中使用更少的时间,这会释放服务器吗?我会以在同一连接上执行更多命令为代价获得更好的 I/O 吞吐量吗?

    6(审核配置):另一部分是查看安装 MySQL 时使用的默认非开发人员配置,也许有一些可以调整的设置? :-)

    感谢阅读,渴望听到任何和所有建议。

    以下仅供引用:

    表:
    CREATE TABLE `message_log` (
        `db_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
        `db_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
        `created` datetime DEFAULT NULL,
        `device_id` int(10) unsigned NOT NULL,
        `display_name` varchar(50) DEFAULT NULL,
        `ignition` binary(1) DEFAULT NULL COMMENT 'This is actually IO8 from the falcom device',
        `sensor_a` float DEFAULT NULL,
        `sensor_b` float DEFAULT NULL,
        `lat` double DEFAULT NULL COMMENT 'default GPRMC format ddmm.mmmm \n',
        `lon` double DEFAULT NULL COMMENT 'default GPRMC longitude format dddmm.mmmm ',
        `heading` float DEFAULT NULL,
        `speed` float DEFAULT NULL,
        `pos_validity` char(1) DEFAULT NULL,
        `device_temp` float DEFAULT NULL,
        `device_volts` float DEFAULT NULL,
        `satellites` smallint(6) DEFAULT NULL, /* TINYINT will suffice */
        `navdist` double DEFAULT NULL,
        `navdist2` double DEFAULT NULL,
        `IO0` binary(1) DEFAULT NULL COMMENT 'Duress',
        `IO1` binary(1) DEFAULT NULL COMMENT 'Fridge On/Off',
        `IO2` binary(1) DEFAULT NULL COMMENT 'Not mapped',
        `msg_name` varchar(20) DEFAULT NULL, /* Will be removed */
        `msg_type` varchar(16) DEFAULT NULL, /* Will be removed */
        `msg_id` smallint(6) DEFAULT NULL,
        `raw` text, /* Not needed in primary query, considering adding to single table mapped to this ID or a UUID correlation ID to save on @ROWID query */
    PRIMARY KEY (`db_id`),
    KEY `Name` (`display_name`),
    KEY `Created` (`created`),
    KEY `DeviceID_AND_Created` (`device_id`,`created`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    DeviceID_AND_Created 是主索引。我需要 PK 聚集索引,因为我在汇总表中使用记录 ID,该记录 ID 跟踪给定设备的最后一条消息。创建的将是分区列,所以我猜它也会被添加到 PK 集群中?

    查询:
    SELECT 
        ml.db_id, ml.db_created, ml.created, ml.device_id, ml.display_name, bin(ml.ignition) as `ignition`, 
        bin(ml.IO0) as `duress`, bin(ml.IO1) as `fridge`,ml.sensor_a, ml.sensor_b, ml.lat, ml.lon, ml.heading, 
        ml.speed,ml.pos_validity, ml.satellites, ml.navdist2, ml.navdist,ml.device_temp, ml.device_volts,ml.msg_id
    FROM message_log ml 
    WHERE ml.device_id = @IMEI
    AND ml.created BETWEEN @STARTDATE AND DATE_ADD(@STARTDATE,INTERVAL 24 hour) 
    ORDER BY ml.db_id;
    

    这将返回给定 24 小时内的所有日志,目前约为。 3k 到 9k 行,平均行大小 381 字节,一旦我删除了 TEXT 字段之一(原始),就会减少

    最佳答案

    Implement ranged partitioning by date: a) Keep monthly partitions. E.g. last 6 months b) Move anything older to archive table.



    这是一个很好的主意。我猜所有的写入都将在最新的分区中,您将只查询最近的数据。您总是希望数据和索引适合内存的情况。所以读取时没有磁盘 i/o。

    根据您的用例,每周有一个分区甚至可能是明智的。然后你只需要在内存中保留最多两周的数据来读取过去 7 天的数据。

    如果您使用 innodb 作为引擎或使用 myisam 引擎时使用 myisam_key_cache,您可能还想调整缓冲区大小(即 innodb_buffer_pool_size)。

    此外,将 ram 添加到 DB 机器通常会有所帮助,因为操作系统可以将数据文件保存在内存中。

    如果您有大量写入,您还可以调整其他选项(即使用 innodb_log_buffer_size 将写入持久化到磁盘的频率)。这是为了让脏页在内存中停留更长时间,以避免将它们过于频繁地写回磁盘。

    关于mysql - MySQL中如何优化大表,什么时候可以从分区中受益?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40520162/

    有关mysql - MySQL中如何优化大表,什么时候可以从分区中受益?的更多相关文章

    1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

      我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

    2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

      总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

    3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

      类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

    4. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

      关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

    5. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

      给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

    6. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

      我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

    7. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    8. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

      我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

    9. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

      我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

    10. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

      我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

    随机推荐