处理大型数据库时如何获得最佳性能?
How can i get the best performance when dealing with large database?
我正在编写一个网页游戏,其中有法术 table、物品 table.. 等。每个 table 都有数千行。我的处理方法如下。
登录后,我将整个数据库存储在用户会话中。这仅包括不会被用户输入更改的 table。例如,咒语 table 仅包含有关咒语的信息。他们造成多少伤害,玩家需要什么等级才能拥有该法术,等等。用户只读取该数据,从不写入它。
假设用户想要购买特定法术。我无法负担 PHP 代码去检查会话变量中的每个数组的拼写 ID。相反 ->
<?php
// Load all database spells
$stmt = $db->prepare("SELECT * FROM spells");
$stmt->execute();
$result = $stmt->fetchAll(\PDO::FETCH_UNIQUE|\PDO::FETCH_ASSOC);
$_SESSION["spells_db"] = $result;
?>
所以,发生的是 -> 我将所有数据库拼写存储到这个会话变量中。使用 \PDO::FETCH_UNIQUE|\PDO::FETCH_ASSOC 我将拼写数组键更改为拼写 ID。这样我就知道了拼写键
如果我需要通过id来搜索法术信息,法术的id也是该法术数组行的键。因此,而不是使用 in_array() 使 PHP 搜索数组的每一行,以查找哪个内部数组包含相关的法术 ID,我可以告诉它它是哪一行。这样我节省了很多性能。
但另一方面,每个单独的用户都将整个数据库存储在他的会话中。这会及时导致我的网站出现可扩展性问题。我知道最好将数据存储在会话中,而不是每次都进行查询以询问数据库是否发生了某些更改。就我而言,当某些内容发生更改时,首先我在会话中更改它,然后我在数据库中更改它。每次用户刷新页面时,都会显示会话数据。但是谈论像存储整个数据库这样的大数据存储,让我头晕目眩。那么,关于如何处理这个问题有什么建议吗?谢谢你的时间。
我建议您先使用数据库进行测试。我想是 MySQL。它可以在 table 中快速处理数 GB 的数据和数百万行。重要的是索引。数千行对于 MySQL 来说并不算多(假设您没有包含多个 varchar(5000) 等的大行)。
(你说的那些键应该是你数据库中的索引table,我有直觉这些是你的自增主键,所以他们会被快速选择。)
PHP 会话数据也必须存储在某个地方
- 如果您将会话存储保留为默认值,则数据将存储在磁盘上的文件中。这意味着磁盘写入和那些比任何现代数据库(即使在 SSD 上)都慢,因为数据库会缓存(到 RAM 中)和优化。
- 如果您将会话存储在 RAM 中并且您确实有很多数据,那么您肯定会 运行 内存不足。
- 如果您将会话存储在数据库中...您知道
亲吻。
如果您同时更新 $_SESSION
和数据库 table,这会增加复杂性、迟缓性等,以及潜在的错误。以及潜在的一致性问题。
假设您要从法术 table 中获取 一个 法术,这将花费大约 1 毫秒。您可以同时进行多个查询 运行。
我建议你在没有$_SESSION的情况下大量使用数据库,时间操作,然后决定哪些需要加速。 然后 添加索引等可能会有帮助。或者切换到 $_SESSION 可能 是必要的。
不要陷入“过早的优化”。
如果您的游戏变得流行,则会出现更大的问题——单个服务器是不够的。但是一旦你将游戏分散到多个服务器上,$_SESSION 就会变得不可用——它仅限于一个服务器。
我正在编写一个网页游戏,其中有法术 table、物品 table.. 等。每个 table 都有数千行。我的处理方法如下。
登录后,我将整个数据库存储在用户会话中。这仅包括不会被用户输入更改的 table。例如,咒语 table 仅包含有关咒语的信息。他们造成多少伤害,玩家需要什么等级才能拥有该法术,等等。用户只读取该数据,从不写入它。
假设用户想要购买特定法术。我无法负担 PHP 代码去检查会话变量中的每个数组的拼写 ID。相反 ->
<?php
// Load all database spells
$stmt = $db->prepare("SELECT * FROM spells");
$stmt->execute();
$result = $stmt->fetchAll(\PDO::FETCH_UNIQUE|\PDO::FETCH_ASSOC);
$_SESSION["spells_db"] = $result;
?>
所以,发生的是 -> 我将所有数据库拼写存储到这个会话变量中。使用 \PDO::FETCH_UNIQUE|\PDO::FETCH_ASSOC 我将拼写数组键更改为拼写 ID。这样我就知道了拼写键
如果我需要通过id来搜索法术信息,法术的id也是该法术数组行的键。因此,而不是使用 in_array() 使 PHP 搜索数组的每一行,以查找哪个内部数组包含相关的法术 ID,我可以告诉它它是哪一行。这样我节省了很多性能。
但另一方面,每个单独的用户都将整个数据库存储在他的会话中。这会及时导致我的网站出现可扩展性问题。我知道最好将数据存储在会话中,而不是每次都进行查询以询问数据库是否发生了某些更改。就我而言,当某些内容发生更改时,首先我在会话中更改它,然后我在数据库中更改它。每次用户刷新页面时,都会显示会话数据。但是谈论像存储整个数据库这样的大数据存储,让我头晕目眩。那么,关于如何处理这个问题有什么建议吗?谢谢你的时间。
我建议您先使用数据库进行测试。我想是 MySQL。它可以在 table 中快速处理数 GB 的数据和数百万行。重要的是索引。数千行对于 MySQL 来说并不算多(假设您没有包含多个 varchar(5000) 等的大行)。
(你说的那些键应该是你数据库中的索引table,我有直觉这些是你的自增主键,所以他们会被快速选择。)
PHP 会话数据也必须存储在某个地方
- 如果您将会话存储保留为默认值,则数据将存储在磁盘上的文件中。这意味着磁盘写入和那些比任何现代数据库(即使在 SSD 上)都慢,因为数据库会缓存(到 RAM 中)和优化。
- 如果您将会话存储在 RAM 中并且您确实有很多数据,那么您肯定会 运行 内存不足。
- 如果您将会话存储在数据库中...您知道
亲吻。
如果您同时更新 $_SESSION
和数据库 table,这会增加复杂性、迟缓性等,以及潜在的错误。以及潜在的一致性问题。
假设您要从法术 table 中获取 一个 法术,这将花费大约 1 毫秒。您可以同时进行多个查询 运行。
我建议你在没有$_SESSION的情况下大量使用数据库,时间操作,然后决定哪些需要加速。 然后 添加索引等可能会有帮助。或者切换到 $_SESSION 可能 是必要的。
不要陷入“过早的优化”。
如果您的游戏变得流行,则会出现更大的问题——单个服务器是不够的。但是一旦你将游戏分散到多个服务器上,$_SESSION 就会变得不可用——它仅限于一个服务器。