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的开销你真的用了吗?

不要索引每一列。查看您的查询并为 列或 列组合编制索引,这些列 SELECTsUPDATEsDELETEs.

将受益

请出示查询;没有他们,我们无法判断性能。