优化慢速索引选择MySql查询

优化慢速索引选择MySql查询,mysql,database,innodb,Mysql,Database,Innodb,我正在尝试使用src_ip上的索引表执行一个简单的select查询,如下所示: 从netflow_nov2中选择*,其中src_IP=311950672 然而,即使在4或5个小时后,这项工作也无法完成。我需要响应在几秒钟的范围内。我想知道我如何才能优化它,所以这就是情况 还请注意,源ip使用内置的SQL命令转换为整数 有关该表的其他信息: 该表包含从nfdump解析的netflow数据。我正在使用该表获取有关特定IP地址的信息。换句话说,基本上只会使用类似上面的查询 以下是“显示表格状态”为该表

我正在尝试使用src_ip上的索引表执行一个简单的select查询,如下所示:

从netflow_nov2中选择*,其中src_IP=311950672

然而,即使在4或5个小时后,这项工作也无法完成。我需要响应在几秒钟的范围内。我想知道我如何才能优化它,所以这就是情况

还请注意,源ip使用内置的SQL命令转换为整数

有关该表的其他信息: 该表包含从nfdump解析的netflow数据。我正在使用该表获取有关特定IP地址的信息。换句话说,基本上只会使用类似上面的查询

以下是“显示表格状态”为该表格提供的相关信息:

Rows: 4,205,602,143 (4 billion)
Data Length: 426,564,911,104 (426 GB)
Index Length: 57,283,706,880 (57 GB)
有关系统的信息: 硬盘:~2TB,使用量接近最大值 内存:64GB

my.cnf文件: 见要点:

表结构:

   mysql> DESCRIBE netflow_nov2;
+-----------+------------------+------+-----+---------+-------+
| Field     | Type             | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+-------+
| date      | datetime         | YES  | MUL | NULL    |       |
| duration  | float            | YES  |     | NULL    |       |
| protocol  | varchar(16)      | YES  |     | NULL    |       |
| src_IP    | int(10) unsigned | YES  | MUL | NULL    |       |
| src_port  | int(2)           | YES  |     | NULL    |       |
| dest_IP   | int(10) unsigned | YES  | MUL | NULL    |       |
| dest_port | int(2)           | YES  |     | NULL    |       |
| flags     | varchar(8)       | YES  |     | NULL    |       |
| Tos       | int(4)           | YES  |     | NULL    |       |
| packets   | int(8)           | YES  |     | NULL    |       |
| bytes     | int(8)           | YES  |     | NULL    |       |
| pps       | int(8)           | YES  |     | NULL    |       |
| bps       | int(8)           | YES  |     | NULL    |       |
| Bpp       | int(8)           | YES  |     | NULL    |       |
| Flows     | int(8)           | YES  |     | NULL    |       |
+-----------+------------------+------+-----+---------+-------+
15 rows in set (0.02 sec)
我有关于explain的索引和结果的其他信息,但简单地说: -索引是b树,有date、src_ip和dest_ip的索引,但实际上只使用src_ip -根据EXPLAIN的输出,src_ip索引用于顶部提到的特定查询

以及mysqltuner的输出: 见要点:

显示创建表输出:

| netflow_nov2 | CREATE TABLE `netflow_nov2` (
  `date` datetime DEFAULT NULL,
  `duration` float DEFAULT NULL,
  `protocol` varchar(16) DEFAULT NULL,
  `src_IP` int(10) unsigned DEFAULT NULL,
  `src_port` int(2) DEFAULT NULL,
  `dest_IP` int(10) unsigned DEFAULT NULL,
  `dest_port` int(2) DEFAULT NULL,
  `flags` varchar(8) DEFAULT NULL,
  `Tos` int(4) DEFAULT NULL,
  `packets` int(8) DEFAULT NULL,
  `bytes` int(8) DEFAULT NULL,
  `pps` int(8) DEFAULT NULL,
  `bps` int(8) DEFAULT NULL,
  `Bpp` int(8) DEFAULT NULL,
  `Flows` int(8) DEFAULT NULL,
  KEY `src_IP` (`src_IP`),
  KEY `dest_IP` (`dest_IP`),
  KEY `date` (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |

提前感谢

我认为阅读没有索引的表格需要不到5个小时。但是你确实有一张大桌子。有两种环境可能性会破坏性能:

该表被另一个进程锁定。 结果集有上千万行,返回结果集的网络延迟/处理时间是导致问题的原因。 不过,我的第一个猜测是,查询没有使用索引。一开始我没注意到,但你有一个多部分索引。此查询可以利用的唯一索引是第一个键为src_IP的索引。所以,如果索引是netflow_nov2src_IP,date,dest_IP或netflow_nov2src_IP,dest_IP,date,那么就可以了。如果其他列中的任何一列是第一列,则不会使用此索引。通过将explain放在查询前面以查看索引是否正在使用,可以很容易地看到发生了什么


如果这是一个问题,请使用src_IP作为索引中的第一个键或唯一键创建索引。

您当前的表结构针对随机写入进行了优化:记录按写入顺序放置在磁盘上

不幸的是,这种结构支持的唯一读取模式是全表扫描。 使用非覆盖二级索引仍然会导致大量随机磁盘搜索,这会破坏性能

当数据以与磁盘上数据相同的顺序读取时,可以获得最佳的读取性能,对于InnoDB来说,这意味着以主键顺序读取

物化视图—另一个具有适当主键的InnoDB表—可能是一个可行的解决方案。在这种情况下,需要以src_IP开头的主键

upd:其思想是实现数据局部性,避免随机磁盘IO,以实现顺序读取。这意味着您的物化视图将如下所示:

CREATE TABLE `netflow_nov2_view` (
  `row_id` bigint not null, -- see below
  `date` datetime DEFAULT NULL,
  `duration` float DEFAULT NULL,
  `protocol` varchar(16) DEFAULT NULL,
  `src_IP` int(10) unsigned DEFAULT NULL,
  `src_port` int(2) DEFAULT NULL,
  `dest_IP` int(10) unsigned DEFAULT NULL,
  `dest_port` int(2) DEFAULT NULL,
  `flags` varchar(8) DEFAULT NULL,
  `Tos` int(4) DEFAULT NULL,
  `packets` int(8) DEFAULT NULL,
  `bytes` int(8) DEFAULT NULL,
  `pps` int(8) DEFAULT NULL,
  `bps` int(8) DEFAULT NULL,
  `Bpp` int(8) DEFAULT NULL,
  `Flows` int(8) DEFAULT NULL,
  PRIMARY KEY (`src_IP`, `row_id`) -- you won't need other keys
) ENGINE=InnoDB DEFAULT CHARSET=latin1
行id必须由具体化逻辑维护,因为原始表中没有行id,或者可以在原始表中引入一个显式的自动增量字段,这就是InnoDB处理行id的方式

关键的区别在于,现在磁盘上的所有数据都按主键顺序排列,这意味着,一旦找到具有给定“src_IP”的第一条记录,就可以尽可能按顺序获取所有其他记录

根据数据的写入方式和相邻的应用程序逻辑,可以通过触发器或某些自定义外部进程来完成

如果可以牺牲当前的写性能或使用一些异步队列作为缓冲区,那么可能有一个为读取优化的表就足够了

有关InnoDB索引的更多信息:

Mul并不意味着复合索引如果Key是Mul,则该列是非唯一索引的第一列,其中允许给定值在该列中多次出现。我非常确定该索引正在使用。EXPLAIN命令表明确实正在使用它:。是的,Mihai的断言是正确的,这些不是多部分键,而是具有非唯一值的键。事实上,每个src_ip可能有数百万个匹配项,这可能是问题所在。能否添加SHOW CREATE TABLE netflow_nov2 Result是否在src_ip字段上有索引或其组件索引以及其他字段?@DmitryBezik SHOW CREATE TABLE已包含在问题的底部。正如您所看到的,在src_ip上确实有一个索引。另外,显示索引输出:查看partitioning@Mihai我喜欢这个主意。你认为我应该基于什么划分?钥匙行id?日期?你能解释一下物化视图表是什么样子吗?我想每一行的索引都是b
e src_ip和值将是存储它们的行的id?我对此有点困惑,如果有任何帮助,我将不胜感激。@SPLASHT0N请查看更新后的内容,希望能有所帮助。我知道这会起作用,但我担心创建索引需要很长时间。不过,我看不到其他解决办法。谢谢你详细的回答。