处理大型数据库时如何获得最佳性能?
Posted
技术标签:
【中文标题】处理大型数据库时如何获得最佳性能?【英文标题】:How can i get the best performance when dealing with large database? 【发布时间】:2021-07-31 08:20:54 【问题描述】:我正在编写一个浏览器游戏,其中有法术表、物品表……等等。每个表都有数千行。我的处理方法如下。
登录后,我将整个数据库存储在用户的会话中。这仅包括不会被用户输入更改的表。例如,spells 表仅包含有关法术的信息。他们造成多少伤害,玩家需要什么等级才能拥有该法术,等等。用户只读取该数据,从不写入。
假设用户想要购买特定的咒语。我无法负担 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,我可以告诉它它是哪一行。这样我节省了很多性能。
但另一方面,每个单独的用户都将整个数据库存储在他的会话中。随着时间的推移,这将导致我的网站出现可扩展性问题。我知道最好将数据存储在会话中,而不是每次都进行查询以询问数据库是否有更改。就我而言,当某些事情发生变化时,首先我在会话中进行更改,然后在数据库中进行更改。并且每次用户刷新页面时,都会显示会话数据。但是谈到像存储整个数据库这样的大数据存储,让我头疼。那么,关于如何处理这个问题的任何建议?感谢您的宝贵时间。
【问题讨论】:
太糟糕了,将整个数据库存储在会话中。这会产生很多无用的 I/O。只需明智地使用数据库索引,并准备语句以供重用。这应该比你现在做的快很多。If they are full, then 15 queries will get triggered in order to get the relevant information for those items(Item name..ect).
...为什么不通过一次查询来获取与玩家相关的所有库存物品?似乎应用程序的实现方式可能存在一些普遍的低效率。
Since the session variable contains data that is never going to be changed, then can i store that data in a text document or something. Simply storing the database tables that are not going to be changed in a text document for more performance
...取决于您需要如何查询数据。您似乎假设数据库访问效率低下。它不是。数据库在扫描和获取大量数据以及按需搜索/过滤和排序方面非常高效,特别是如果您在表上设置了正确的索引并具有合理的架构设计。
I know that it is better to store data in the session, instead making query every time to ask the database if something is changed
... 通常仅适用于您在每个请求中访问的小东西,例如当前用户的姓名和 ID。如果您确实对数据库 I/O 有问题(您没有提供任何实际证据),那么可能是切向提到的缓存解决方案可能是合适的,但再次取决于您是否需要搜索/过滤/排序每个数据您访问它的时间。
ADyson 非常感谢您的回答。是的,我认为数据库访问效率低下。由于以下原因,我使用了 15 个查询。有一个名为 playerinventory 的表,它的每一列都像“slot1”、“slot2”.. 等。这些列包含数字(项目 ID)。那么在 PHP 中,如果相关的 slot 不为 0,那么 PHP 会访问另一个名为 items 的表,例如它包含数千行。它会查询每个 ID 不为 0 的玩家位置。
【参考方案1】:
亲吻。
如果您同时更新$_SESSION
和数据库表,这会增加复杂性、迟缓性等以及潜在的错误。以及潜在的一致性问题。
假设您正在从法术表中获取 一个 法术,这将花费大约 1 毫秒。您可以同时运行多个查询。
我建议你在没有$_SESSION的情况下大量使用数据库,时间操作,然后决定哪些需要加速。 然后添加索引等可能会有所帮助。或者切换到 $_SESSION 可能是必要的。
不要陷入“过早的优化”。
如果你的游戏流行起来,就会出现一个更大的问题——单个服务器是不够的。但是一旦你将游戏分散到多台服务器上,$_SESSION 就变得无法使用——它仅限于一台服务器。
【讨论】:
这对我帮助很大。感谢您花时间回复。 @Diablo13 - 欢迎您。欢迎使用 ***。【参考方案2】:我建议您先使用数据库对其进行测试。我想它的mysql。它可以快速处理表中的千兆字节数据和数百万行。重要的是索引。数千行对于 MySQL 来说并不算多(假设您没有包含多个 varchar(5000) 等的大行)。
(您所说的那些键可能应该是数据库表中的索引,我有直觉认为这些是您的自动增量主键,因此它们会被快速选择。)
PHP Session 数据也必须存储在某个地方
如果您将会话存储保留为默认设置,则数据将存储在磁盘上的文件中。这意味着磁盘写入速度比任何现代数据库(甚至在 SSD 上)都要慢,因为数据库会缓存(到 RAM)并进行优化。 如果您将会话存储在 RAM 中并且确实有大量数据,那么您肯定会用完 RAM。 如果您将会话存储在数据库中...您知道【讨论】:
感谢您的回答。我阅读了我需要知道的所有内容。我想我必须重新从 0 开始。浪费了这么多时间。我有一个程序员朋友,他以编程为主要工作 6 年,他告诉我这样做。在我的脑海中,我已经在想象如何以正确的方式修复我构建的所有内容。以上是关于处理大型数据库时如何获得最佳性能?的主要内容,如果未能解决你的问题,请参考以下文章