草庐IT

mysql - 什么会导致 InnoDB 表的单个 UPDATE 性能非常低?

coder 2023-10-23 原文

我的网络应用程序中有一个表用于存储 session 数据。它表现不佳,我不明白为什么。慢速查询日志显示更新一行需要 6 到 60 秒。

CREATE TABLE `sessions` (
    `id` char(40) COLLATE utf8_unicode_ci NOT NULL,
    `payload` text COLLATE utf8_unicode_ci NOT NULL,
    `last_activity` int(11) unsigned NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `session_id_unique` (`id`) USING HASH
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

PK 是一个 char(40),它存储由该项目使用的框架 (Laravel) 生成的唯一 session 哈希。

(我知道 PK 和唯一索引的冗余,但我已经尝试了所有组合,并且它对我的测试性能没有任何影响。这是它的当前状态。)

表格很小 - 不到 200 行

来自慢速查询日志的典型查询如下所示:

INSERT INTO sessions (id, payload, last_activity) 
VALUES ('d195825ddefbc606e9087546d1254e9be97147eb', 
        'YTo1OntzOjY6Il90b2tlbiI7czo0MDoi...around 700 chars...oiMCI7fX0=', 
        1405679480) 
ON DUPLICATE KEY UPDATE 
    payload=VALUES(payload), last_activity=VALUES(last_activity);

我做过很明显的事情,比如检查表格是否损坏。我试过添加一个专用的 PK 列作为自动增量 int,我试过没有 PK,没有唯一索引,将 text 列换成非常非常大 varchar,随你便。

我已经尝试将表切换为使用 MyISAM,但它仍然很慢。

我所做的一切似乎都没有任何区别 - 表格执行速度非常慢。

我的下一个想法是查询。这是由框架生成的,但如果失败,我已经测试过将其破解成带有 INSERTUPDATEUPDATE 语句继续缓慢。

我读过很多关于慢速 INSERTUPDATE 语句的问题,但这些问题通常与批量交易有关。这只是每个用户每个请求的一个插入/更新。该站点不是远程繁忙,它在自己的 VPS 上,资源丰富。

什么可能导致速度缓慢?

最佳答案

这不是答案,但 SE 评论长度太短了。所以。

如果您直接在命令行上运行相同的 INSERT ... ON DUPLICATE KEY UPDATE... 语句会发生什么情况?请在实际使用和不使用该应用程序的情况下进行尝试。应用程序可能人为地减慢了这个更新(例如,在 INNODB 中一个事务可能被打开,但是在消耗了很多时间之后提交。你也用不支持事务的 MyISAM 进行了测试。也许在那种情况下一个显式的 LOCK 可以占同样的效果。如果框架使用这个trick,我不确定,我不知道laravel)尝试进行基准测试,看看是否有并发效果。

另一个问题:这是单台服务器吗?或者它是复制到一个或多个从机的主机?

除了这个问题,还有一些观察:

  • id 的值是十六进制字符串。该列是 unicode。这意味着 3*40 个字节被保留,而只有 40 个被使用。这是一种浪费,通常会使事情效率低下。使用 BINARY 或 ASCII 作为字符编码会好得多。更好的是,将 id 列更改为 BINARY 数据类型并存储(未十六进制的)二进制值
  • innodb PK 表的散列将跨页面分散数据。使用 auto_incrment pk 或根本不显式声明 pk(这将导致 innodb 在内部创建它自己的自动增量 pk)的想法是个好主意。
  • 看起来负载是 base64 编码的。再次将字符编码指定为 unicode。 Ascii 或二进制(字符编码,而不是数据类型)更为合适。
  • ID唯一索引中的HASH关键字无意义。 InnoDB 没有实现 HASH 索引。不幸的是,MySQL 对此完全保持沉默(参见 http://bugs.mysql.com/bug.php?id=73326)

(虽然这个列表确实提供了改进的角度,但似乎不太可能用这个来解决极度缓慢的问题。一定有其他事情发生了)

关于mysql - 什么会导致 InnoDB 表的单个 UPDATE 性能非常低?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24823217/

有关mysql - 什么会导致 InnoDB 表的单个 UPDATE 性能非常低?的更多相关文章

  1. 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

  2. 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

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

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

  4. 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%

  5. 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

  6. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  7. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  8. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  9. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

  10. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

随机推荐