如何加速高度活跃的大数据表(MySQL)?

如何加速高度活跃的大数据表(MySQL)?,mysql,Mysql,我将开始尝试解释我的问题以及我对标题的意思。 目前我有一张大约800万行的桌子。 这个表是高度活跃的,这意味着有不断的更新、插入和删除。 这些都是由用户造成的,就像一个收集游戏。这意味着我还需要确保数据准确显示 到目前为止,我已经研究过: 索引 分割 分片 地图还原 优化 我应用了索引,但是我不确定我是否正确地应用了这个方法,而且它似乎没有比我想象的更大的帮助 正如我所说的,我的表是高度活跃的,这意味着如果我将分区添加到这个表中,这将意味着将有额外的插入/删除,并使这个过程变得比我所能理解的更复

我将开始尝试解释我的问题以及我对标题的意思。 目前我有一张大约800万行的桌子。 这个表是高度活跃的,这意味着有不断的更新、插入和删除。 这些都是由用户造成的,就像一个收集游戏。这意味着我还需要确保数据准确显示

到目前为止,我已经研究过:

索引 分割 分片 地图还原 优化 我应用了索引,但是我不确定我是否正确地应用了这个方法,而且它似乎没有比我想象的更大的帮助

正如我所说的,我的表是高度活跃的,这意味着如果我将分区添加到这个表中,这将意味着将有额外的插入/删除,并使这个过程变得比我所能理解的更复杂。我在数据库方面没有那么多经验

分割这个数据库对我来说太复杂了,我只有一个服务可以运行这个数据库,所以这个选项是不可行的

至于mapreduce,我不完全确定它的作用,但据我所知,它主要是通过代码而不是数据库来实现的

我应用了优化,但它并没有像我所经历的那样产生太多的效果

我尽量不在SELECT语句中使用*,我确保去掉SQL中最独特的、COUNT和其他功能,这样就不会影响数据库的速度。 然而,即使缩小了每个表中的数据范围,特别是这个表中的数据范围,它现在也比之前慢了

该表包括:

CREATE TABLE `claim` (
   `global_id` bigint NOT NULL AUTO_INCREMENT,
   `fk_user_id` bigint NOT NULL,
   `fk_series_id` smallint NOT NULL,
   `fk_character_id` smallint NOT NULL,
   `fk_image_id` int NOT NULL,
   `fk_gif_id` smallint DEFAULT NULL,
   `rarity` smallint NOT NULL,
   `emoji` varchar(31) DEFAULT NULL,
   PRIMARY KEY (`global_id`),
   UNIQUE KEY `global_id_UNIQUE` (`global_id`),
   KEY `fk_claim_character_id` (`fk_character_id`),
   KEY `fk_claim_image_id` (`fk_image_id`),
   KEY `fk_claim_series_id` (`fk_series_id`),
   KEY `fk_claim_user_id` (`fk_user_id`) /*!80000 INVISIBLE */,
   KEY `fk_claim_gif_id` (`fk_gif_id`) /*!80000 INVISIBLE */,
   KEY `fk_claim_rarity` (`rarity`) /*!80000 INVISIBLE */,
   KEY `fk_claim_emoji` (`emoji`),
   CONSTRAINT `fk_claim_character_id` FOREIGN KEY (`fk_character_id`) REFERENCES `character` (`character_id`) ON DELETE CASCADE ON UPDATE CASCADE,
   CONSTRAINT `fk_claim_image_id` FOREIGN KEY (`fk_image_id`) REFERENCES `image` (`image_id`) ON DELETE CASCADE ON UPDATE CASCADE,
   CONSTRAINT `fk_claim_series_id` FOREIGN KEY (`fk_series_id`) REFERENCES `series` (`series_id`) ON DELETE CASCADE ON UPDATE CASCADE,
   CONSTRAINT `fk_claim_user_id` FOREIGN KEY (`fk_user_id`) REFERENCES `user` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE
 ) ENGINE=InnoDB AUTO_INCREMENT=7622452 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
是否有其他解决方案来加速数据库?如果是,怎么做?我现在束手无策,一筹莫展。数据库最好在300ms内响应

慢速查询示例:

SELECT PK FROM <table> WHERE fk_user_id = ?;
SELECT PK FROM <table> WHERE fk_user_id = ? GROUP BY fk_character_id HAVING MAX(fk_character_id) = 1;
SELECT PK, fk_user_id, fk_character_id, etc, etc, etc FROM <table> WHERE fk_user_id = ? ORDER BY PK ASC LIMIT 0, 20
多余的

在MySQL中,主键是唯一的键。因此,唯一密钥是冗余的,浪费了磁盘空间,降低了插入速度

需要以Q1和Q2的用户id开始的可见索引

替换这个

   KEY `fk_claim_user_id` (`fk_user_id`) /*!80000 INVISIBLE */,

按此顺序-这将有助于处理前2个查询

问题3

第三个查询可能仍需要按给定顺序执行

INDEX(fk_user_id, global_id)
如果您需要一些DISTINCTs/计数,我们来看看。更改索引可能会有所帮助

奇怪的疑问

至于

SELECT PK FROM <table> WHERE fk_user_id = ?;
如果已知某些列xx的用户标识xx是唯一的,则抛出全局标识并更改为

PRIMARY KEY(user_id, xx) 
无论哪种情况,这些都会消失:

PRIMARY KEY (`global_id`),
UNIQUE KEY `global_id_UNIQUE` (`global_id`),
KEY `fk_claim_user_id` (`fk_user_id`) /*!80000 INVISIBLE */,
InnoDB按主键顺序存储数据。通过让PK以user_id开始,一个用户的所有行在磁盘上都是相邻的,因此更容易缓存在buffer_池中的RAM中


给定一个拥有100个声明的用户,我正在重新构造该表,以便InnoDB在16KB存储单元的两个连续块中找到数据,而不是在100个以上分散的块中找到数据。

您运行的哪个查询速度低于预期速度?你能包括表格结构吗?你能包括解释选择的输出吗?现在800万条记录绝对不是大数据。80亿可能是。不幸的是,您的问题太模糊,无法提供任何具体帮助,因为通常的编程答案是使用索引。您需要向我们展示一个表现不佳的查询,我们可以帮助您加快查询速度。您还需要查看mysql的配置,因为它也会对性能产生很大影响。@zedfoxus几乎所有与SELECT相关的语句都需要10秒以上的响应时间。除非我加上一个限制。例如,从特定用户获取所有项目。这只不过是用一个WHERE to the FK of user来获取PK。表结构如文中所述,我对它引用的FKs没有任何问题。输出是来自实际用户的机密数据,但输出返回的结果与您对文本中表格示例的预期一致。@Shadow我根据请求添加了一些示例查询,我知道这些查询运行速度非常慢。此表格包含:不是表结构的定义。请发布SHOW CREATE TABE\G的输出以获得更完整的表定义。您是一个绝对的英雄!我很挣扎,因为DISTINCT确实似乎无法很好地处理数据量,但一旦我应用了您建议的索引,它就发挥了巨大的作用。
PRIMARY KEY(user_id, global_id), -- for locality of reference
INDEX(global_id)  -- to keep AUTO_INCREMENT happy
PRIMARY KEY(user_id, xx) 
PRIMARY KEY (`global_id`),
UNIQUE KEY `global_id_UNIQUE` (`global_id`),
KEY `fk_claim_user_id` (`fk_user_id`) /*!80000 INVISIBLE */,