一个字面上的疯狂答案,但是如果您设置了某种复制系统(对于具有十亿行的系统,希望如此),则可以使用粗略估计器(例如 MAX(pk)
),将该值除以从属数您可以并行运行多个查询。
在大多数情况下,您将以最佳方式(或我猜的主键)在从属服务器上对查询进行分区,方式是这样(我们将使用250000000作为行/从属设备):
-- First slave
SELECT COUNT(pk) FROM t WHERE pk < 250000000
-- Ith slave where 2 <= I <= N - 1
SELECT COUNT(pk) FROM t WHERE pk >= I*250000000 and pk < (I+1)*250000000
-- Last slave
SELECT COUNT(pk) FROM t WHERE pk > (N-1)*250000000
但是您只需要SQL。真是破门 好的,假设您是一名施虐受虐狂。在主服务器(或最接近的从服务器)上,您最可能需要为此创建一个表:
CREATE TABLE counter_table (minpk integer, maxpk integer, cnt integer, slaveid integer)
因此,您不仅需要在自己的奴隶中运行选择,还需要执行插入操作,类似于此:
INSERT INTO counter_table VALUES (I*25000000, (I+1)*250000000, (SELECT COUNT(pk) FROM ... ), @@SLAVE_ID)
从站向主站上的表写入数据可能会遇到问题。您可能需要变得更加悲伤-我是说,富有创造力:
-- A table per slave!
INSERT INTO counter_table_slave_I VALUES (...)
最后,相对于第一个从属服务器,在复制图所遍历的路径中最后应该存在一个从属服务器。该从站现在应该具有所有其他计数器值,并且应该具有自己的值。但是,当您完成操作时,可能已经添加了几行,因此您必须插入另一行,以补偿counter_table中记录的最大pk和当前的最大pk。
到那时,您必须执行一个汇总函数来计算总行数,但这会更容易,因为您最多只能在“拥有并更改的从站数量”行上运行它。
如果您在从属服务器中有单独的表,则可以UNION
获取所需的所有行。
SELECT SUM(cnt) FROM (
SELECT * FROM counter_table_slave_1
UNION
SELECT * FROM counter_table_slave_2
UNION
...
)
或者您知道,可以将数据迁移到分布式处理系统上,或者再使用数据仓库解决方案(这也将使您将来处理令人敬畏的数据)更加省力。
请注意,这确实取决于您的复制设置得如何。由于主要瓶颈很可能是持久性存储,因此,如果您的存储空间比较粗糙,或者数据存储的隔离性很差,并且邻居噪音很大,那么这可能会比仅等待单个存储慢一些。SELECT COUNT(*) ...
但是,如果您具有良好的复制能力,那么您的速度提升应该与数量或从属数量直接相关。实际上,如果仅运行计数查询需要10分钟,并且您有8个从属,则您可以将时间减少到不到两分钟。可能需要一个小时来解决此解决方案的细节。
当然,您永远不会真正得到一个非常准确的答案,因为这种分布式解决方案会花一些时间删除和插入行,但是您可以尝试在同一实例上获取分布式行锁并获得精确的计数表中特定时间段的行数。
实际上,这似乎是不可能的,因为您基本上只能使用仅SQL的解决方案,而且我认为您没有提供一种可在多个从属服务器上立即运行分片和锁定查询的机制。也许,如果您控制了复制日志文件……这意味着您实际上是为此目的而从动纺纱奴隶,这无疑比仅在单台机器上运行计数查询要慢。
因此,我有两个便士。