3

让我们在这里和我一起假装:

PHP/MySQL 网络应用程序。假设一个服务器和一个 MySQL DB。

我有1000个老板。每个老板手下有10个工人。work orders这 10 个工作人员(乘以 1k,总计 10,000 个工作人员)每个工作日在 WebApplication中至少有 5 个数据库条目(为此目的调用它们)。在此工作订单表中,每天有 50k 个条目

除了服务器问题,我在这里看到了两种处理数据库基本逻辑的主要方法:

  1. 每个Boss都有一个ID。有一个名为的表workorders,它有一个名为BossID将每个工单与老板相关联的列。这样一来,您每个月在一个表中就有大约 100 万个条目,对我来说,这似乎加起来很快。

  2. 每个 Boss 都有自己的,该表是在该 Boss 注册时创建的,即work_bossIDwhere bossID = the boss' unique ID。这会给您留下 1,000 个表,但这些表更易于管理。


  • 我忽略了第三种选择吗?

  • 哪种方法会是效果更好的方法?

  • 对于表中的条目数来说有多大(假设列数很少:小于 10)?(这可能包括:是时候获得第二台服务器了……)

  • 数据库中的表数量有多大?(这可能包括:是时候获得第二台服务器了……)

我知道在某些时候我们必须讨论多台服务器和链接在一起的数据库......但是,让我们再次关注具有单个 MySQL DB 的单个服务器。

4

4 回答 4

3

如果您使用单个服务器,我认为表的大小没有问题。它不仅是表中的记录数,还包括访问频率。

要管理大型数据集,您可以使用多个服务器。在这种情况下:

  • 您可以将所有工作订单保存在一个表中,并将它们镜像到不同的服务器(以便您拥有从属服务器)

  • 您可以按老板对工单表进行分片(在这种情况下,您根据工单所属的位置访问服务器)- 搜索数据库分片以获取更多信息

您选择哪个选项取决于您将如何使用数据库。


镜子(主/从)

将所有工单保存在一个表中有助于在您不知道工单属于哪个老板时进行查询,例如。如果您按产品类型搜索,但任何老板都可以在任何产品类型中下订单。

但是,您必须在每个镜像上存储所有内容的副本。此外,只有一台服务器(主服务器)可以处理更新(或添加工单)SQL 请求。如果您的大多数 SQL 查询都是 SELECT 查询,这很好。


分片

分片的优点是您不必在每个镜像服务器上都存储记录的副本。

但是,如果您正在通过某个属性搜索任何老板的工单,则必须查询每个服务器以检查每个分片。


如何选择

总之,如果您可以进行各种查询,包括按属性浏览工单(除了它属于哪个老板),请使用单个表,并且您可能有更多的 SELECT(读取)查询而不是写入查询。

如果您可以将写入查询的数量级与读取查询的数量级相同,并且/或者您想节省内存,并且通过其他属性(不是老板)搜索的查询很少见,请使用分片。


保持快速查询

大型数据库如果不被查询淹没的话并不是什么大问题,因为它们可以将大部分数据库保存在硬盘上,并且只将最近访问的内容保存在缓存中(在内存上)。

防止任何单个查询运行缓慢的另一件重要事情是确保为可能执行的每个查询添加正确的索引以避免线性搜索。这是为了允许数据库对所需的记录进行二分搜索。

如果您需要维护记录计数,无论是整个表还是按属性(类别或老板),然后保持计数器缓存。

何时获得新服务器

由于变量太多,您实际上无法分配一个数字来确定何时需要新服务器。可以通过查看查询的执行速度以及服务器的 CPU/内存使用情况来做出此决定。

于 2012-08-18T02:25:38.483 回答
1

扩展通常是一个实验案例,因为从一开始并不总是清楚瓶颈在哪里。由于您似乎对系统将承受的负载类型有一个很好的了解,因此首先要做的事情之一就是在电子表格中记录这一点,以便您可以制定一些假设。这使您可以做很多快速的“假设”场景,并为您在第一次构建时必须扩展多远提出一个合理的上限。

为了收集大量记录,有一些简单的规则:

  • 使用最有效的数据类型来表示您所描述的内容。不要担心使用较小的整数类型来减少几个字节,或者缩小 varchars。这里重要的是使用整数表示数字,使用日期字段表示日期,等等。不要将 varchar 用于已经具有正确类型的数据。
  • 不要过度索引您的表,只添加绝对必要的内容。您拥有的索引数量越多,随着表的增长,插入的速度就越慢。
  • 清除不再需要的数据。哪里实用删除它。在需要长时间保留的地方,制作可以将其转储到的备用表。例如,您可以每季度或每财年轮换一次主订单表,以保持其快速运行。如果需要报告,您可以随时调整查询以针对其他表运行。使您的工作数据集尽可能小。
  • 通过基准测试、修补、研究和试验来调整您的 MySQL 服务器。这里没有灵丹妙药。有许多变量可能对某些人有用,但可能会减慢您的应用程序。它们还高度依赖于操作系统、硬件以及数据的结构和大小。通过为数据库引擎(例如 InnoDB 或 MyISAM)分配更多内存,您可以轻松地将性能提高一倍或四倍。
  • 如果您认为它们可能有很大帮助,请尝试使用其他 MySQL 分支。有一些提供了比常规 MySQL 更高的性能,特别是Percona
  • 如果您经常且积极地查询大型表,则对某些数据进行反规范化以减少必须完成的昂贵连接的数量可能是有意义的。例如,在留言板上,您可能会在每条消息中包含用户名,尽管这看起来很浪费数据,但它可以非常非常快地显示大量消息列表。

考虑到所有这些,最好的办法是设计您的模式,构建您的表,然后使用它们。模拟加载 6-12 个月的数据,看看它在真正加载后的表现如何。EXPLAIN如果您使用较慢的查询,您会发现各种问题。最好在比生产数据库服务器慢的开发系统上执行此操作,这样在部署时不会有任何意外。

扩展的黄金法则是只优化实际存在的问题,并避免仅仅因为它看起来是个好主意而对其进行调整。过度设计一个解决方案非常容易,该解决方案稍后会与您的意图相反或被证明极难撤销。

如果您在推出之前仔细试验并证明它在一定容量下工作,MySQL 可以处理数百万甚至数十亿行而不会有太多麻烦。

于 2012-08-18T04:20:22.593 回答
-1

我的一个网络也有数据库大小问题,它太大了,当我对该表运行查询时,它会降低服务器速度。

在我看来,将您的数据库划分为日期决定什么表大小对您来说太大了 - 比如说 100 万个条目,然后计算您需要多长时间才能达到这个数量。然后每隔一段时间都有一个脚本来创建一个带有日期的新表并将所有当前数据移到上面,或者只是备份该表并将其清空。

就像把过时的材料放在档案馆里一样。

如果您选择第一个选项,您将能够通过参考该表轻松访问该日期。

希望这个想法有帮助

于 2012-08-18T03:13:40.660 回答
-2

只需为两者创建一个工人表、老板表、关系表,然后创建所有其他表。有了这样的关系结构,它是非常动态的。因为,如果它变得足够大,您可以在工作订单与老板或工人之间创建另一个关系表。


您可能想研究 bigints,但我怀疑您是否需要它。我知道关系表会变得很大,但那是很好的数据库设计。

当然 bigint 是针对 mySQL 的,它可以正常上到 -9223372036854775808 到 9223372036854775807。0 到 18446744073709551615 未签名*

于 2012-08-18T02:24:38.860 回答