分片MySQL表的最佳方法是什么。我能想到的方法是:
- 应用程序级别分片?
- 在MySQL代理层进行分片?
- 中央查找服务器用于分片吗?
您是否知道该领域中任何有趣的项目或工具?
Answers:
分片MySQL表不这样做的最好方法,除非这样做是完全不可避免的。
在编写应用程序时,通常希望以最大化速度和开发者速度的方式进行编写。仅在必要时才对延迟(直到准备好答案的时间)或吞吐量(每时间单位的答案数)进行优化。
仅当所有这些分区的总和不再适合单个数据库服务器实例时,才对分区进行分区,然后将其分配给不同的主机(=分片)-原因是写入或读取。
写的情况是a)写入频率使该服务器磁盘永久过载,或者b)正在进行过多的写操作,因此复制永久滞后于此复制层次结构中。
分片的读取情况是数据的大小太大,以致其工作集不再适合内存,并且数据读取开始击中磁盘,而不是大部分时间从内存中获取数据。
仅在必须分片时才这样做。
分片后,您会以多种方式为此付费:
您的大部分SQL不再是声明性的。
通常,在SQL中,您是在告诉数据库所需的数据,然后将其留给优化器以将其转换为数据访问程序。这是一件好事,因为它很灵活,而且因为编写这些数据访问程序是无聊的工作,会损害速度。
在分片环境中,您可能正在将节点A上的表与节点B上的数据连接起来,或者在节点A和B上具有比节点大的表,并将来自该表的数据与节点B和C上的数据连接起来。为了解决该问题,您开始手动编写基于应用程序端的基于哈希的连接解析(或者您正在重塑MySQL集群),这意味着您最终会得到很多不再声明性的SQL,而是以过程方式表达SQL功能的SQL。 (例如,您在循环中使用SELECT语句)。
您将招致很多网络延迟。
通常,SQL查询可以在本地解决,优化器会了解与本地磁盘访问相关的成本,并以使成本最小化的方式来解析查询。
在分片环境中,可以通过以下方式解决查询:在网络上对多个节点运行键值访问(希望通过批量键访问,而不是每次往返都进行单个键查找),或者通过将WHERE
子句的一部分向前推到可以进行访问的节点上或同时应用(称为“条件下推”)。
但是,即使在最好的情况下,这也要涉及比本地情况更多的网络往返,并且更加复杂。尤其是由于MySQL优化器对网络延迟一无所知(好吧,MySQL群集正在慢慢变得更好,但是对于群集之外的原始MySQL来说仍然如此)。
您正在失去大量的SQL表达能力。
好的,这也许不太重要,但是外键约束和其他SQL数据完整性机制无法跨越多个分片。
MySQL没有API允许按工作顺序进行异步查询。
当相同类型的数据驻留在多个节点上(例如,节点A,B和C上的用户数据)时,通常需要针对所有这些节点解析水平查询(“查找90天未登录的所有用户帐户”或者更多”)。数据访问时间随节点数线性增长,除非可以并行请求多个节点并且结果随输入而汇总(“ Map-Reduce”)。
前提条件是异步通信API,对于MySQL来说,它尚不具备良好的工作状态。另一种选择是在子过程中进行大量分叉和建立联系,这正在访问整个季节过程。
一旦开始分片,数据结构和网络拓扑将成为您应用程序的性能指标。为了合理地执行性能,您的应用程序需要了解这些内容,这意味着实际上只有应用程序级分片才有意义。
问题是更多的,如果您想自动分片(例如,通过对主键进行散列来确定哪一行进入哪个节点),或者您想以手动方式进行功能拆分(“与xyz用户故事相关的表将转到此主表,而与abc和def相关的表将转到该主表”)。
功能分片的优势在于,如果操作正确,大多数时候大多数开发人员都看不到它,因为与用户故事相关的所有表都可以在本地使用。这使他们仍然可以尽可能长时间地受益于声明式SQL,并且由于跨网络传输的次数保持最小,因此还可以减少网络延迟。
功能分片的缺点是它不允许任何单个表都大于一个实例,并且需要设计人员的手动注意。
功能分片的优点是,相对容易地对现有代码库进行了很多更改,但变化不算太大。在过去的几年中,http://Booking.com做了多次,对他们来说效果很好。
说了这么多,看着你的问题,我相信你在问错问题,或者我完全误解了你的问题陈述。
应用程序级别分片:dbShards是我所知道的唯一一种“应用程序感知分片”的产品。网站上有一些不错的文章。就像定义一样,应用程序感知分片将更加高效。如果应用程序确切地知道要去哪里进行事务而不必查找它或由代理重定向,那么它本身将更快。当有人正在研究分片时,速度通常是首要考虑的问题之一,即使不是唯一考虑的问题。
有些人通过代理进行“分片”,但是在我看来,这无法达到分片的目的。您只是在使用另一台服务器来告诉您的交易,在哪里可以找到数据或在哪里存储数据。通过应用程序感知分片,您的应用程序可以知道自己要去哪里。效率更高。
确实与#2相同。
您是否知道该领域中任何有趣的项目或工具?
这个领域中的几个新项目:
分片查询是用于MySQL的基于OLAP的分片解决方案。它允许您定义分片表和未分片表的组合。未分片的表(例如查找表)可以自由地与分片的表连接,并且分片的表可以彼此连接,只要这些表通过分片键进行连接即可(无交叉分片或跨分片边界的自连接)。作为OLAP解决方案,Shard-Query通常具有100ms或更短的最小响应时间,即使对于简单查询也是如此,因此它不适用于OLTP。分片查询旨在并行分析大数据集。
OLTP分片解决方案也适用于MySQL。封闭源解决方案包括ScaleDB,DBShards。开源OLTP解决方案包括JetPants,Cubrid或Flock / Gizzard(Twitter基础架构)。
应用水平当然。
这本书中我发现过的最好的方法
高性能MySQL http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064
简短说明:您可以将数据分成许多部分,并在每台服务器上存储约50个部分。这将帮助您避免分片的第二大问题-重新平衡。只要将它们中的一些移到新服务器上,一切就可以了:)
我强烈建议您购买并阅读“ mysql扩展”部分。
截至2018年,似乎有一个MySql本机解决方案。实际上至少有2个-InnoDB集群和NDB集群(有商业版本和社区版本)。
由于大多数使用MySql社区版的人对InnoDB引擎更加熟悉,因此应首先探索这一点。它支持开箱即用的复制和分区/分片,并且基于MySql Router提供不同的路由/负载平衡选项。
创建表的语法需要更改,例如:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );
(这只是四种分区类型之一)
一个非常重要的限制:
InnoDB外键和MySQL分区不兼容。分区的InnoDB表不能具有外键引用,也不能具有被外键引用的列。具有或由外键引用的InnoDB表无法分区。
PARTITION BY HASH(YEAR...)
它将扫描所有分区。uck