通过将表一分为二进行MySQL优化

通过将表一分为二进行MySQL优化,mysql,Mysql,我目前有一个名为map\u tiles的表,它最终将有大约二十万行。此表中的每一行代表我的游戏世界地图上的一个单独磁贴。目前,表结构如下所示: id int(11) PRIMARY KEY city_id int(11) type varchar(20) x int(11) INDEX KEY y int(11) INDEX KEY level int(11) 我还希望能够存储一个字符串化的JSON对象,该对象将包含有关该特定磁贴的

我目前有一个名为
map\u tiles
的表,它最终将有大约二十万行。此表中的每一行代表我的游戏世界地图上的一个单独磁贴。目前,表结构如下所示:

id      int(11)    PRIMARY KEY
city_id int(11)
type    varchar(20)
x       int(11)    INDEX KEY
y       int(11)    INDEX KEY
level   int(11)
我还希望能够存储一个字符串化的JSON对象,该对象将包含有关该特定磁贴的信息。因为我可能有100000多行,所以我想优化我的查询和表设计,以获得尽可能好的性能

下面是我的场景:玩家加载一个位置,比如说世界地图上的50,50。我们将加载玩家坐标25个瓷砖半径内的所有瓷砖。因此,我们必须在我的
map\u tiles
表中的这张数十万行的表上运行
WHERE
查询

那么,向现有表中添加另一个名为
data
text
类型的字段会证明性能更好吗?但是,这会减慢主查询的速度

或者,是否值得创建一个名为
map\u tiles\u data
的单独表,其结构如下:

tile_id int(11) PRIMARY KEY
data    text
我可以运行主查询,从
map\u tiles
中查找播放器半径范围内的tile,然后执行
UNION ALL
,可能只是从第二个表中提取JSON字符串化的
数据


编辑:对不起,我应该澄清一下。如果使用第二个表,则
map\u tiles
表中的每个对应tile都不会有一行。仅当数据存储在地图分幅上时,才会添加行。因此,默认情况下,
map\u tiles\u data
表中将有0行,而
map\u tiles
表中可能有100000行。当玩家执行x动作时,游戏将在地图数据中添加一行,将数据存储在一个或两个表中并不是你的主要问题。问题是如何获得相邻的瓷砖。我一会儿再谈这个问题

JSON可以是灵活存储属性/值对的方便格式。但是,它对于访问数据库中的数据并不是很有用。您可能需要考虑混合形式。这建议使用另一个表,因为您可能希望偶尔添加或删除列

另一个考虑是保持历史。您可能需要JSON组件的历史记录,但对于其余的数据不需要。这建议使用单独的表格

至于优化
的位置
。我想你有三个选择。首先是你目前的做法,这是不合理的

第二个是第三个表,其中包含给定距离内的所有邻居(每个磁贴一行和每个相邻磁贴一行)。不幸的是,这种方法不允许您轻松地改变半径,这可能是可取的


最好的解决方案是使用GIS解决方案。您可以研究MySQL对地理数据类型的支持。

JSON的存储位置其实并不重要。您面临的主要性能问题是,
WHERE
子句将无法使用任何索引(因为您最终执行的是大于/小于查询,而不是固定查询)。十万行并不是那么多,所以这个简单解决方案的性能对于您的用例来说是可以接受的;理想情况下,您应该使用MySQL支持的地理空间类型。

无需将数据存储在单独的表中。你可以用同一张桌子。但您必须使用InnoDB插件并设置
InnoDB\u file\u format=barracuda
,由于数据将是文本,请使用
ROW\u format=Dynamic(或Compressed)

InnoDB将文本存储在行页面之外,因此将数据放在同一个表中比放在单独的表中更有效(可以避免连接和外键)。还可以在x和y上添加索引,因为所有查询都基于位置

有用的阅读:

Innodb插件采用“Barracuda”格式,行\格式=动态。在这种格式中,Innodb在行页面上存储整个blob,或者只存储20字节的blob指针,优先选择要存储在页面上的较小列,这是合理的,因为您可以存储更多列。blob可以有前缀索引,但这不再需要在页面上存储列前缀——您可以在blob上构建前缀索引,这些blob通常存储在页面之外

压缩行格式在处理blob时类似于DYNAMIC,并且将使用相同的策略将blob完全存储在页面之外。但是,它将始终压缩不适合行页面的blob,即使未指定KEY_BLOCK_SIZE,并且未启用普通数据和索引页面的压缩

不要以为我指的只是斑点。Innodb以同样的方式处理来自存储的BLOB、文本以及长VARCHAR


Ref:

当您请求json对象时,是否始终需要该对象中的所有数据?如果你用的话,我不能怪你用它。如果您在给定时间只需要json对象中存储的一些信息,那么这是对空间的浪费。根据您使用的编程语言,您可能能够序列化数据,而不是将其设置为字符串,从而节省一些存储容量。@Sumurai8感谢您的响应!是的,几乎每个从
map\u tiles
数据库中提取行的查询都将使用JSON数据,除了一个查询可能在另一个主查询运行时间的1%之外。感谢您的响应。我已经更新了我的帖子以包含索引。:)你好首先,谢谢你的回复。请允许我问一下,我目前的方法是什么意思,我不知道你的参考是哪一位。第三个表将证明是一个问题,因为正如你所提到的,在任何时候我都可以更新游戏,以更改加载相邻瓷砖的半径。至于地理信息系统,这是必要的吗?我只是简单地装了些瓷砖