mysql 中存储大约 4.5 亿行给定数据的最佳数据库结构是什么
What will be the best database structure in mysql to store approx 450 million rows of given data
示例数据
"Service_Area_Code" | "Phone_Numbers" | "Preferences" | "Opstype" | "Phone_Type"
13 9827259163 0 A 2
13 9827961481 0 D 2
11 9827202228 0 A 2
2 9827529897 0 D 2
13 9827700249 0 A 2
我的结构
CREATE TABLE `master` (
`circle` tinyint(4) NOT NULL,
`phone` bigint(10) NOT NULL,
`prefrences` varchar(16) NOT NULL,
`ops_type` varchar(1) NOT NULL,
`phone_type` tinyint(4) NOT NULL,
PRIMARY KEY (`phone`)
) ENGINE=InnoDB
- 对我来说这是一个好的数据库结构吗?
- 我应该将此数据拆分为多个 table 还是一个 table 足以容纳所有数据。
- 我的服务器配置是 4GB Ram、2GB Vswap、4 核 CPU 和 125GB HDD,因此考虑到以上所有情况,请建议我部署此数据库的最佳方法。
查询会是什么样子?需要看他们来判断INDEXes
要包括什么。
对于 450M 行,尽可能缩小数据类型很重要。
所有文本都是 ASCII 码吗?如果是CHARACTER SET ascii
。然后选择是否要大小写折叠:COLLATE ascii_general_ci
vs ascii_bin
.
varchar(1)
也可能是 CHAR(1) DEFAULT ' '
(或其他一些 suitable 默认值)。
bigint(10)
将允许 19 位数字和可选的前导破折号(减号)。你会过滤掉破折号和括号吗? (我希望如此。)这仅限于美国吗? (10)
意味着这样。在任何情况下,BIGINT
占用 8 个字节; DECIMAL(10,0)
占用 5 个字节。 (11,0) 也需要 5; 12 或 13 取 6;等等
preferences
显示为数字 0
,但定义为 VARCHAR
。确定数字或字符串,否则您可能会遇到一些意外。还要考虑 SET
数据类型,它只需要 2 个字节来指定 16 个二进制选项的任意组合。
尽可能使用 UNSIGNED
。 (示例:TINYINT UNSIGNED
给出的范围是 0-255。)
不要不要将它分成多个table。这将是一个令人头疼的编码问题, 没有 性能优势。 PARTITIONing
是另一种拆分形式,但在我们看到查询之前,我怀疑它是否会带来 任何 好处。
450M 与 10M 或 10B 没有太大区别。如果你有 万亿 行,我会担心行数。
根据我的建议并添加 suitable 索引,您的 table 将占用大约 20G-30GB。使用 innodb_buffer_pool_size = 1000M
(大约适合您的 4GB 小型机器),table 肯定不能完全缓存,复杂的查询需要特别注意。 (同样,我们不能在没有看到查询的情况下完成这个问题。)
如何加载
鉴于您有大约 45 个 CSV 文件,每个文件有 1000 万行,并且 CSV 文件未排序,以下是我建议的合理高速加载:
CREATE TABLE master ( ... ) ENGINE=InnoDB; -- as already discussed
CREATE TABLE t ( ... ) ENGINE=MyISAM; -- Same columns, but no index, not even PK.
foreach CSV file, do 3 steps:
LOAD DATA ... INTO t ... -- load one CSV file: a few minutes
INSERT INTO master
SELECT * FROM t ORDER BY phone;
TRUNCATE TABLE t; -- a few seconds
DROP TABLE t; -- when finished.
如果您需要对数据进行任何处理,可以在 LOAD DATA
内部或之后完成。
前几个 INSERT..SELECTs
会非常快,因为所有内容都已缓存。到最后一个 CSV 时,该步骤将明显变慢。但是整体速度可能acceptable。我希望 "a few days" 能做到这一切。
示例数据
"Service_Area_Code" | "Phone_Numbers" | "Preferences" | "Opstype" | "Phone_Type"
13 9827259163 0 A 2
13 9827961481 0 D 2
11 9827202228 0 A 2
2 9827529897 0 D 2
13 9827700249 0 A 2
我的结构
CREATE TABLE `master` (
`circle` tinyint(4) NOT NULL,
`phone` bigint(10) NOT NULL,
`prefrences` varchar(16) NOT NULL,
`ops_type` varchar(1) NOT NULL,
`phone_type` tinyint(4) NOT NULL,
PRIMARY KEY (`phone`)
) ENGINE=InnoDB
- 对我来说这是一个好的数据库结构吗?
- 我应该将此数据拆分为多个 table 还是一个 table 足以容纳所有数据。
- 我的服务器配置是 4GB Ram、2GB Vswap、4 核 CPU 和 125GB HDD,因此考虑到以上所有情况,请建议我部署此数据库的最佳方法。
查询会是什么样子?需要看他们来判断INDEXes
要包括什么。
对于 450M 行,尽可能缩小数据类型很重要。
所有文本都是 ASCII 码吗?如果是CHARACTER SET ascii
。然后选择是否要大小写折叠:COLLATE ascii_general_ci
vs ascii_bin
.
varchar(1)
也可能是 CHAR(1) DEFAULT ' '
(或其他一些 suitable 默认值)。
bigint(10)
将允许 19 位数字和可选的前导破折号(减号)。你会过滤掉破折号和括号吗? (我希望如此。)这仅限于美国吗? (10)
意味着这样。在任何情况下,BIGINT
占用 8 个字节; DECIMAL(10,0)
占用 5 个字节。 (11,0) 也需要 5; 12 或 13 取 6;等等
preferences
显示为数字 0
,但定义为 VARCHAR
。确定数字或字符串,否则您可能会遇到一些意外。还要考虑 SET
数据类型,它只需要 2 个字节来指定 16 个二进制选项的任意组合。
尽可能使用 UNSIGNED
。 (示例:TINYINT UNSIGNED
给出的范围是 0-255。)
不要不要将它分成多个table。这将是一个令人头疼的编码问题, 没有 性能优势。 PARTITIONing
是另一种拆分形式,但在我们看到查询之前,我怀疑它是否会带来 任何 好处。
450M 与 10M 或 10B 没有太大区别。如果你有 万亿 行,我会担心行数。
根据我的建议并添加 suitable 索引,您的 table 将占用大约 20G-30GB。使用 innodb_buffer_pool_size = 1000M
(大约适合您的 4GB 小型机器),table 肯定不能完全缓存,复杂的查询需要特别注意。 (同样,我们不能在没有看到查询的情况下完成这个问题。)
如何加载
鉴于您有大约 45 个 CSV 文件,每个文件有 1000 万行,并且 CSV 文件未排序,以下是我建议的合理高速加载:
CREATE TABLE master ( ... ) ENGINE=InnoDB; -- as already discussed
CREATE TABLE t ( ... ) ENGINE=MyISAM; -- Same columns, but no index, not even PK.
foreach CSV file, do 3 steps:
LOAD DATA ... INTO t ... -- load one CSV file: a few minutes
INSERT INTO master
SELECT * FROM t ORDER BY phone;
TRUNCATE TABLE t; -- a few seconds
DROP TABLE t; -- when finished.
如果您需要对数据进行任何处理,可以在 LOAD DATA
内部或之后完成。
前几个 INSERT..SELECTs
会非常快,因为所有内容都已缓存。到最后一个 CSV 时,该步骤将明显变慢。但是整体速度可能acceptable。我希望 "a few days" 能做到这一切。