MySql - 用于大型表IP配对的更好的架构?

时间:2016-09-20 12:06:56

标签: mysql optimization schema normalization

我试图管理一些互联网日志。我基本上捕获了哪些IP正在接触哪些IP并对其进行报告。

问题是有大量的喋喋不休,我不确定我是否可以更好地制作我的架构。

我的表架构:

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;

现在我已经获得了2千行数据并在大约4秒内收回了我需要的数据。然而,这是使用相对较轻的测试数据。我想象最终产品中数据的大小要大30倍。所以4秒肯定意味着最终产品需要2分钟。有没有更好的方法可以将这些数据标准化,或者让我碰到瓶颈,我无能为力?另外,我选择的索引是否正常?

2 个答案:

答案 0 :(得分:0)

没关系,我明白了。我想我只需要输入问题来帮助我思考解决方案。

因此,在查看我的数据之后,我注意到很多配对都是重复的,但是在不同的FKToSomeTableWithExtraMetaDataId值下。

所以告诉我,我可以通过创建一个包含SourceIp , DestinationIp , SourcePort , DestinationPort`的不同配对的表来规范化数据。然后创建一个查找表,将该表与ToSomeTableWithExtraMetaData表连接起来。

这使我的原始IP数据减少了1700%!在搜索一系列IP时,这将大大提高性能,现在它的行数要少得多。再加上查找表,我可以更灵活地查询。

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;

答案 1 :(得分:0)

缩小桌子尺寸。较小的是一种帮助(某些)速度的方法。

IPv4可以打包到INT UNSIGNED,与当前的8字节BIGINT相比为4个字节。另一方面,IPv6需要BINARY(16);你所拥有的将无法发挥作用。

我认为端口号将适合2字节SMALLINT UNSIGNED

您是否预计您的桌子会超过40亿行?如果没有,请使用INT UNSIGNED而不是BIGINT作为ID。

摆脱FOREIGN KEYs,他们放慢了速度;同时,约束从未引发错误,是吗?你真的使用CASCADE的开销吗?

不要为每列编制索引。查看您的查询并将列或列的列编入索引,这些列将使SELECTsUPDATEsDELETEs受益。

请出示查询;没有它们,我们无法判断其表现。