我试图管理一些互联网日志。我基本上捕获了哪些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分钟。有没有更好的方法可以将这些数据标准化,或者让我碰到瓶颈,我无能为力?另外,我选择的索引是否正常?
答案 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
的开销吗?
不要为每列编制索引。查看您的查询并将列或列的列编入索引,这些列将使SELECTs
,UPDATEs
和DELETEs
受益。
请出示查询;没有它们,我们无法判断其表现。