Dav*_*ger 5 mysql delete memory btree
我运行一个大型论坛,该论坛维护用于后端数据存储的 MySQL 数据库。“会话”表跟踪登录的用户和来宾。目前大约有 10 万条记录,所以不是那么大。但是,当我们修剪旧记录时,这个会话表会出现在慢查询日志中:
# Time: 120719 10:05:11
# User@Host: xxx[xxx] @ [10.x.x.x]
# Thread_id: 369051896 Schema: forumdb Last_errno: 0 Killed: 0
# Query_time: 8.352811 Lock_time: 0.000028 Rows_sent: 0 Rows_examined: 19635 Rows_affected: 19635 Rows_read: 0
# Bytes_sent: 13 Tmp_tables: 0 Tmp_disk_tables: 0 Tmp_table_sizes: 0
SET timestamp=1342710311;
DELETE FROM session
WHERE lastactivity < 1342709401;
Run Code Online (Sandbox Code Playgroud)
我已经确认 lastactivity 表上有一个 BTREE 索引:
mysql> SHOW INDEX FROM session FROM forumdb;
+---------+------------+--------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+--------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| session | 0 | PRIMARY | 1 | sessionhash | NULL | 78941 | NULL | NULL | | HASH | | |
| session | 1 | userid | 1 | userid | NULL | 26313 | NULL | NULL | | HASH | | |
| session | 1 | idhash | 1 | idhash | NULL | 8771 | NULL | NULL | | HASH | | |
| session | 1 | userid_2 | 1 | userid | NULL | NULL | NULL | NULL | | HASH | | |
| session | 1 | userid_2 | 2 | lastactivity | NULL | 39470 | NULL | NULL | | HASH | | |
| session | 1 | userid_3 | 1 | userid | NULL | NULL | NULL | NULL | | HASH | | |
| session | 1 | userid_3 | 2 | host | NULL | 39470 | NULL | NULL | | HASH | | |
| session | 1 | lastactivity | 1 | lastactivity | A | NULL | NULL | NULL | | BTREE | | |
+---------+------------+--------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
8 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
我很好奇为什么删除查询需要这么长时间的记录。
应该注意的是,该表被大量使用,同时有这么多用户在线。我们有一些沉重的硬件坐在它后面。
关于我可以做些什么来加快这个过程的任何想法?它似乎正在锁定表,因此在执行此删除功能时,我会看到集群中的高负载。
查询缓存已关闭(我们使用 memcache)。这是 my.cnf 的相关部分:
table_open_cache=8242
table_definition_cache=600
open_files_limit=65535
binlog_cache_size=6M
sort_buffer_size=8M
key_buffer_size=5G
myisam_sort_buffer_size=256M
join_buffer_size=3M
thread_cache_size=1000
thread_concurrency=16
ft_min_word_len=3
tmp_table_size=512M
max_allowed_packet=128M
max_heap_table_size=512M
read_rnd_buffer_size=1M
skip-external-locking
query_cache_limit=1M
query_cache_size= 32M
query_cache_type = 0
Run Code Online (Sandbox Code Playgroud)
最后,这里有一些关于表的更多信息:

将表更改为 InnoDB 后(下图中的 17:15),我看到性能要好得多,并且该表的慢日志中不再有 DELETE。自从进行此更改后,整个集群的性能都得到了提高。谢谢你。

我可能会将您的 Memory 表转换为 InnoDB
ALTER TABLE session ENGINE=InnoDB
Run Code Online (Sandbox Code Playgroud)
对于你的情况。内存表适用于低写入、多次读取,如果丢失数据(例如加载配置值),您并不在意。但是当你开始写很多东西时,如果你有很多连接访问它,表锁就会杀死你:
尽管内存中处理 MEMORY 表,但它们不一定比繁忙服务器上的 InnoDB 表快,用于通用查询,或在读/写工作负载下。特别是,执行更新所涉及的表锁定会减慢来自多个会话的 MEMORY 表的并发使用。[源代码]
由于不关心数据丢失,跟踪会话数据似乎是一个不错的选择,但我认为在这种情况下,通过切换到 InnoDB,您可能会获得删除表锁的显着好处。