MySql - 大型 table IP 配对的更好架构?
MySql - Better Schema for large table IP pairings?
我正在尝试管理一些互联网日志。我本质上是在捕获哪些 IP 正在接触其他哪些 IP,并就此生成报告。
问题是有大量的喋喋不休,我不确定我是否可以使我的模式更好。
我的 table 架构:
CREATE TABLE `IpChatter` (
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`SourceIp` bigint(20) NULL,
`DestinationIp` bigint(20) NULL,
`SourcePort` int(11) NULL,
`DestinationPort` int(11) NULL,
`FKToSomeTableWithExtraMetaDataId` bigint(20) NOT NULL,
CONSTRAINT `PK_IpChatter` PRIMARY KEY (`Id` ASC)
) ENGINE=InnoDB;
CREATE INDEX `IX_IpChatter_FKToSomeTableWithExtraMetaDataId` ON `IpChatter` (`FKToSomeTableWithExtraMetaDataId`) using HASH;
CREATE INDEX `IX_IpChatter_Main_Query_SourceIp` ON `IpChatter` (`SourceIp`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationIp` ON `IpChatter` (`DestinationIp`);
CREATE INDEX `IX_IpChatter_Main_Query_SourcePort` ON `IpChatter` (`SourcePort`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationPort` ON `IpChatter` (`DestinationPort`);
ALTER TABLE `IpChatter` ADD CONSTRAINT `FK_IpChatter_FKToSomeTableWithExtraMetaData`
FOREIGN KEY (`FKToSomeTableWithExtraMetaDataId`) REFERENCES `FKToSomeTableWithExtraMetaData` (`Id`)
ON DELETE CASCADE;
现在我有 2mill 行数据并在大约 4 秒内拉回我需要的数据。然而,这是来自使用相对较轻的测试数据。我想象最终产品中的数据大小会大 30 倍。所以 4 秒在最终产品中肯定意味着 2 分钟。有没有更好的方法可以规范化这些数据,或者我是否遇到瓶颈而我无能为力?另外,我选择的索引可以吗?
没关系,我想通了。我想我只需要输入问题来帮助我想出解决方案。
所以在查看我的数据后,我注意到很多配对是重复的,但在不同的 FKToSomeTableWithExtraMetaDataId 值下。
So 告诉我,我可以通过创建一个 table 与 SourceIp,
DestinationIp,
SourcePort,
DestinationPort` 的不同配对来规范化数据。然后创建一个查找 table 以将 table 与 ToSomeTableWithExtraMetaData table 连接起来。
这使我的原始 IP 数据减少了 1700%!这将在搜索一系列 IP 时显着提高性能,现在它必须遍历更少的行。加上查找 table 我在查询方式上有更大的灵活性。
CREATE TABLE `IpChatter` (
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`SourceIp` bigint(20) NULL,
`DestinationIp` bigint(20) NULL,
`SourcePort` int(11) NULL,
`DestinationPort` int(11) NULL,
`FKToSomeLookupTableId` bigint(20) NOT NULL,
CONSTRAINT `PK_IpChatter` PRIMARY KEY (`Id` ASC)
) ENGINE=InnoDB;
CREATE INDEX `IX_IpChatter_FKToSomeLookupTableId` ON `IpChatter` (`FKToSomeLookupTableId`) using HASH;
CREATE INDEX `IX_IpChatter_Main_Query_SourceIp` ON `IpChatter` (`SourceIp`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationIp` ON `IpChatter` (`DestinationIp`);
CREATE INDEX `IX_IpChatter_Main_Query_SourcePort` ON `IpChatter` (`SourcePort`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationPort` ON `IpChatter` (`DestinationPort`);
ALTER TABLE `IpChatter` ADD CONSTRAINT `FK_IpChatter_FKToSomeLookupTable`
FOREIGN KEY (`FKToSomeLookupTableId`) REFERENCES `FKToSomeLookupTable` (`Id`)
ON DELETE CASCADE;
CREATE TABLE `FKToSomeLookupTable` (
`FKToSomeTableWithExtraMetaDataId` bigint(20) NOT NULL,
`IpChatterId` bigint(20) NOT NULL,
CONSTRAINT `PK_FKToSomeLookupTable` PRIMARY KEY (`Id` ASC)
) ENGINE=InnoDB;
CREATE INDEX `IX_IpChatter_FKToSomeTableWithExtraMetaDataId` ON `FKToSomeLookupTable` (`FKToSomeTableWithExtraMetaDataId`) using HASH;
CREATE INDEX `IX_IpChatter_IpChatterId` ON `FKToSomeLookupTable` (`IpChatterId`) using HASH;
ALTER TABLE `FKToSomeLookupTable` ADD CONSTRAINT `FK_FKToSomeLookupTable_FKToSomeTableWithExtraMetaData`
FOREIGN KEY (`FKToSomeTableWithExtraMetaDataId`) REFERENCES `FKToSomeTableWithExtraMetaData` (`Id`)
ON DELETE CASCADE;
ALTER TABLE `FKToSomeLookupTable` ADD CONSTRAINT `FK_FKToSomeLookupTable_IpChatter`
FOREIGN KEY (`IpChatterId`) REFERENCES `IpChatter` (`Id`)
ON DELETE CASCADE;
缩小 table 大小。更小是帮助(某些)提高速度的一种方法。
IPv4 可以打包成 INT UNSIGNED
,这是 4 个字节,而您当前的 8 字节 BIGINT。另一方面,IPv6 需要 BINARY(16)
;你有什么不会工作。
端口号,我认为,将适合 2 个字节 SMALLINT UNSIGNED
。
您是否希望 table 超过 40 亿行?如果不是,请使用 INT UNSIGNED
而不是 BIGINT
作为 ID。
去掉 FOREIGN KEYs
,它们会减慢速度;同时,约束从未触发过错误,是吗? CASCADE
的开销你真的用了吗?
不要索引每一列。查看您的查询并为 列或 列组合编制索引,这些列 SELECTs
、UPDATEs
和 DELETEs
.
将受益
请出示查询;没有他们,我们无法判断性能。
我正在尝试管理一些互联网日志。我本质上是在捕获哪些 IP 正在接触其他哪些 IP,并就此生成报告。
问题是有大量的喋喋不休,我不确定我是否可以使我的模式更好。
我的 table 架构:
CREATE TABLE `IpChatter` (
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`SourceIp` bigint(20) NULL,
`DestinationIp` bigint(20) NULL,
`SourcePort` int(11) NULL,
`DestinationPort` int(11) NULL,
`FKToSomeTableWithExtraMetaDataId` bigint(20) NOT NULL,
CONSTRAINT `PK_IpChatter` PRIMARY KEY (`Id` ASC)
) ENGINE=InnoDB;
CREATE INDEX `IX_IpChatter_FKToSomeTableWithExtraMetaDataId` ON `IpChatter` (`FKToSomeTableWithExtraMetaDataId`) using HASH;
CREATE INDEX `IX_IpChatter_Main_Query_SourceIp` ON `IpChatter` (`SourceIp`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationIp` ON `IpChatter` (`DestinationIp`);
CREATE INDEX `IX_IpChatter_Main_Query_SourcePort` ON `IpChatter` (`SourcePort`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationPort` ON `IpChatter` (`DestinationPort`);
ALTER TABLE `IpChatter` ADD CONSTRAINT `FK_IpChatter_FKToSomeTableWithExtraMetaData`
FOREIGN KEY (`FKToSomeTableWithExtraMetaDataId`) REFERENCES `FKToSomeTableWithExtraMetaData` (`Id`)
ON DELETE CASCADE;
现在我有 2mill 行数据并在大约 4 秒内拉回我需要的数据。然而,这是来自使用相对较轻的测试数据。我想象最终产品中的数据大小会大 30 倍。所以 4 秒在最终产品中肯定意味着 2 分钟。有没有更好的方法可以规范化这些数据,或者我是否遇到瓶颈而我无能为力?另外,我选择的索引可以吗?
没关系,我想通了。我想我只需要输入问题来帮助我想出解决方案。
所以在查看我的数据后,我注意到很多配对是重复的,但在不同的 FKToSomeTableWithExtraMetaDataId 值下。
So 告诉我,我可以通过创建一个 table 与 SourceIp,
DestinationIp,
SourcePort,
DestinationPort` 的不同配对来规范化数据。然后创建一个查找 table 以将 table 与 ToSomeTableWithExtraMetaData table 连接起来。
这使我的原始 IP 数据减少了 1700%!这将在搜索一系列 IP 时显着提高性能,现在它必须遍历更少的行。加上查找 table 我在查询方式上有更大的灵活性。
CREATE TABLE `IpChatter` (
`Id` bigint(20) NOT NULL AUTO_INCREMENT,
`SourceIp` bigint(20) NULL,
`DestinationIp` bigint(20) NULL,
`SourcePort` int(11) NULL,
`DestinationPort` int(11) NULL,
`FKToSomeLookupTableId` bigint(20) NOT NULL,
CONSTRAINT `PK_IpChatter` PRIMARY KEY (`Id` ASC)
) ENGINE=InnoDB;
CREATE INDEX `IX_IpChatter_FKToSomeLookupTableId` ON `IpChatter` (`FKToSomeLookupTableId`) using HASH;
CREATE INDEX `IX_IpChatter_Main_Query_SourceIp` ON `IpChatter` (`SourceIp`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationIp` ON `IpChatter` (`DestinationIp`);
CREATE INDEX `IX_IpChatter_Main_Query_SourcePort` ON `IpChatter` (`SourcePort`);
CREATE INDEX `IX_IpChatter_Main_Query_DestinationPort` ON `IpChatter` (`DestinationPort`);
ALTER TABLE `IpChatter` ADD CONSTRAINT `FK_IpChatter_FKToSomeLookupTable`
FOREIGN KEY (`FKToSomeLookupTableId`) REFERENCES `FKToSomeLookupTable` (`Id`)
ON DELETE CASCADE;
CREATE TABLE `FKToSomeLookupTable` (
`FKToSomeTableWithExtraMetaDataId` bigint(20) NOT NULL,
`IpChatterId` bigint(20) NOT NULL,
CONSTRAINT `PK_FKToSomeLookupTable` PRIMARY KEY (`Id` ASC)
) ENGINE=InnoDB;
CREATE INDEX `IX_IpChatter_FKToSomeTableWithExtraMetaDataId` ON `FKToSomeLookupTable` (`FKToSomeTableWithExtraMetaDataId`) using HASH;
CREATE INDEX `IX_IpChatter_IpChatterId` ON `FKToSomeLookupTable` (`IpChatterId`) using HASH;
ALTER TABLE `FKToSomeLookupTable` ADD CONSTRAINT `FK_FKToSomeLookupTable_FKToSomeTableWithExtraMetaData`
FOREIGN KEY (`FKToSomeTableWithExtraMetaDataId`) REFERENCES `FKToSomeTableWithExtraMetaData` (`Id`)
ON DELETE CASCADE;
ALTER TABLE `FKToSomeLookupTable` ADD CONSTRAINT `FK_FKToSomeLookupTable_IpChatter`
FOREIGN KEY (`IpChatterId`) REFERENCES `IpChatter` (`Id`)
ON DELETE CASCADE;
缩小 table 大小。更小是帮助(某些)提高速度的一种方法。
IPv4 可以打包成 INT UNSIGNED
,这是 4 个字节,而您当前的 8 字节 BIGINT。另一方面,IPv6 需要 BINARY(16)
;你有什么不会工作。
端口号,我认为,将适合 2 个字节 SMALLINT UNSIGNED
。
您是否希望 table 超过 40 亿行?如果不是,请使用 INT UNSIGNED
而不是 BIGINT
作为 ID。
去掉 FOREIGN KEYs
,它们会减慢速度;同时,约束从未触发过错误,是吗? CASCADE
的开销你真的用了吗?
不要索引每一列。查看您的查询并为 列或 列组合编制索引,这些列 SELECTs
、UPDATEs
和 DELETEs
.
请出示查询;没有他们,我们无法判断性能。