【问题标题】:Why is this query slow? Should I use MyISAM rather than InnoDB here?为什么这个查询很慢?我应该在这里使用 MyISAM 而不是 InnoDB 吗?
【发布时间】:2010-03-02 00:13:38
【问题描述】:

在我的慢查询日志中,我每小时大约会收到 5 次这些:

# Query_time: 11.420629  Lock_time: 0.000033 Rows_sent: 0  Rows_examined: 0
SET timestamp=1267487708;
INSERT INTO record_lock (record_lock.module_id, record_lock.module_record_id, record_lock.site_id, record_lock.user_id, record_lock.expiration_date_time, record_lock.date_time_created) VALUES ('40', '12581', '940', '155254', '2010-03-02 00:24:57', '2010-03-01 23:54:57');

# Query_time: 2.095374  Lock_time: 0.000031 Rows_sent: 0  Rows_examined: 0
SET timestamp=1267488361;
DELETE
FROM record_lock
WHERE record_lock.user_id = 221659 AND record_lock.expiration_date_time IS NOT NULL;

record_lock 表目前使用 InnoDB,现在它有不到十几个记录。

我们的系统中有数千名活跃用户。每次他们编辑记录时,我们都会插入到这个表中。在系统中任何地方的每个页面加载时,我们 1)从表中选择以查看当前用户是否有任何锁,以及 2)如果有用户的任何记录,则对该表运行 DELETE 查询,引用WHERE 子句中表的主键。

这是表的架构:

CREATE TABLE IF NOT EXISTS `record_lock` (
  `module_id` int(10) unsigned NOT NULL,
  `module_record_id` int(10) unsigned NOT NULL,
  `site_id` int(10) unsigned NOT NULL,
  `user_id` int(10) unsigned NOT NULL,
  `expiration_date_time` datetime NOT NULL,
  `date_time_created` datetime DEFAULT NULL,
  PRIMARY KEY (`module_id`,`module_record_id`),
  KEY `record_lock_site_id` (`site_id`),
  KEY `index_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

【问题讨论】:

    标签: mysql innodb myisam record-locking


    【解决方案1】:

    你每秒执行多少查询?

    您能不能在记录本身中放置一个锁定字段?我想你无论如何都会得到记录。您还可以使用 memcached 之类的东西来存储锁。

    我不知道具体细节,但我的理解是 InnoDB 非常适合并发读取,但不适合并发写入。 MyISAM 可能会更好,但我的直觉告诉我当前的设计存在缺陷。

    【讨论】:

    • InnoDB 对于写入量大的应用程序比读取量大的应用程序要好得多。
    • 我完全同意 memcached 的想法。如果我们找不到进一步的优化,这可能是我们前进的方向。
    • 好吧,为了优化,您可能需要查看 MyTop 以观察进程,查看插入/更新/删除的比率等。我认为我们需要更多关于什么是在优化它之前进行。您知道该表被写入和删除的频率吗?是否只有 12 条记录,但它们每秒都在变化?
    • 好的,我得到以下结果:0.29 次插入/秒,0.03 次更新/秒,0.09 次删除/秒,20365.73 次读取/秒。 20.37K 读取/秒似乎很多——你同意吗?我不确定 20K 读取是否都是同一张表。
    • 哇!这对我来说似乎很重要。 1000 将是一个相当大的数字。您能否分享更多关于在典型页面加载时检查多少锁的信息?是否有一个循环的 cron 作业在某处运行?
    【解决方案2】:

    您是否尝试过对查询运行 EXPLAIN?

    【讨论】:

    • 不,我从未使用过 EXPLAIN。我试试看。
    • 针对该表的 SELECT 查询的 EXPLAIN 没有什么突出的。
    【解决方案3】:

    是否有太多的连接试图访问同一张表?您可以尝试在 user_id 上对表进行分段以帮助解决此问题。

    【讨论】:

    • 嗯,感谢您的意见,但从数据库管理的角度来看,这听起来非常、非常混乱。
    • 连接过多真的应该是 InnoDB 和几千个用户的问题吗?
    【解决方案4】:

    打开 Innodb 监视器有助于缩小性能不佳的原因:

    SHOW ENGINE INNODB STATUS and the InnoDB Monitors

    【讨论】:

    • 好的,我得到以下结果:0.29 次插入/秒,0.03 次更新/秒,0.09 次删除/秒,20365.73 次读取/秒。 20.37K 读取/秒似乎很多——你同意吗?我不确定 20K 读取是否都是同一张表。我还收到“表record_lock 的外键约束失败”。外键约束失败会减慢速度吗?
    • 我在记录锁定表中看不到外键约束。你有从其他表到记录锁表的限制吗?再次查看慢日志条目 - 锁不会保持很长时间,记录锁表很小,因此实际语句应该不会花费时间:只是您的系统在做其他工作时已经用尽了吗? 20k 读取/秒可以做到这一点。 “iostat -dx”的输出如何查看您的数据库? cpu是固定的吗? %实用程序?你试过监视器吗?它可以提供很多关于争用等的详细信息。
    • 另一个想法:如果您认真使用 MySQL,那么这本 O'Reilly 的书物有所值:“高性能 MySQL:优化、备份、复制等”
    猜你喜欢
    • 1970-01-01
    • 2019-09-07
    • 2016-05-05
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 2016-10-06
    • 2011-03-11
    • 1970-01-01
    相关资源
    最近更新 更多