【发布时间】:2015-09-12 15:57:03
【问题描述】:
假设有一个包含十亿行的大表,我使用以主键为参数的散列函数将其拆分为 1000 个表,分别包含一百万行。查询和更新的速度会不会变快?
【问题讨论】:
-
一千个表 = 一千个名称 = 一千个不同的选择/更新语句,您必须根据散列键派生这些语句。只是说'
标签: database relational-database
假设有一个包含十亿行的大表,我使用以主键为参数的散列函数将其拆分为 1000 个表,分别包含一百万行。查询和更新的速度会不会变快?
【问题讨论】:
标签: database relational-database
答案是:它取决于数据、分区、您的查询,尤其是索引。
如果您按日期拆分,这样的分区是有意义的。通过这种方式,历史数据通常会从事务性存储中移出到报告或仓储数据库中。
我想知道您是否需要索引。您应该在 WHERE 子句中的列上有索引。
解释慢查询的计划并寻找表扫描。
十亿行并不稀奇。
【讨论】:
通常在 INSERT/UPDATE/DELETE 时保持索引更新会产生开销,数据库引擎应该有足够的内存来将所有索引和数据保存在缓冲区中以避免冗余 I/O。了解每个表的索引和数据大小 (MySQL) 会很有帮助:
SET @db_name = 'you_database';
SELECT
TBname,
CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(102,pw),3),',',''),17,' '),' ', SUBSTR(' KMGTP',pw,1),'B') "Data Size",
CONCAT(LPAD(REPLACE(FORMAT(B.ISize/POWER(102,pw),3),',',''),17,' '),' ', SUBSTR(' KMGTP',pw,1),'B') "Index Size",
CONCAT(ROUND(B.ISize * 100 / B.DSize), ' %') "Percentage",
CONCAT(LPAD(REPLACE(FORMAT(B.TSize/POWER(102,pw),3),',',''),17,' '),' ', SUBSTR(' KMGTP',pw,1),'B') "Table Size"
FROM
(SELECT table_name TBname, data_length DSize, index_length ISize, data_length+index_length TSize
FROM information_schema.tables WHERE table_schema = @db_name) B,
(SELECT 3 pw) A ORDER BY ISize DESC, DSize DESC
维基百科says:
索引是任何可以提高性能的数据结构 抬头。有许多不同的数据结构用于此 目的。存在涉及查找的复杂设计权衡 性能、索引大小和索引更新性能。多指标 设计表现出对数 O(log(N)) 查找性能,并且在某些情况下 应用程序可以实现平坦的 O(1) 性能。
如果数据库表的数量与文件名的数量相对应,请注意这些事情:
就 O(1) 算法复杂度而言,数据库大小并不重要,但除非您的数据和索引适合内存,否则瓶颈是磁盘 I/O(即使对于 SSD 磁盘也是如此)。另一方面,数据库配置可能需要完全符合 ACID,最终会非常频繁地刷新到磁盘,然后在负载下在更大的数据库上性能下降。
回到原来的问题。将大表拆分为多个小表以加快索引管理的速度是有意义的,从而在小数据集上执行得更好(并且消耗更少的内存)。如果分片键很难找到,您可以考虑使用月份和年份作为表名后缀的替代命名约定(posts -> posts_2015_06、posts_2015_07、posts_2015_08)或归档策略(posts -> posts_archive、posts_fresh)。这取决于针对历史数据发生的 INSERT/UPDATE/DELETE 请求的数量。
【讨论】: