这是我的情况:
我得到了超过 10G 的网络日志(大约 3000 万行),我主要用各种条件搜索它。
例如:
select * from tbl
where ip = '123.123.12.3'
and agent = 'mozillar'
and body like '%script%'
随着数据越来越大,一个简单的查询需要几分钟,所以我试图用 MySQL 集群创建一些分布式数据库。
我在 Google 云虚拟机上构建了 1 个管理服务器、1 个 SQL (api) 服务器和 4 个数据节点。每个实例有 2 个 CPU 和 8 GB。
问题:
当我尝试从 .sql 文件恢复数据时,每个插入语句几乎需要 2~3 秒!
3 秒 * 30m 行 = 永远!
选择查询也让我很失望,它比普通 InnoDB 花费了将近 100 倍的时间。
难道我做错了什么?
有没有更好的解决方案适合我的目的?
配置文件
[ndbd default]
NoOfReplicas=2
DataMemory=5G
IndexMemory=128M
MaxNoOfConcurrentOperations=1000000
MaxNoOfLocalOperations=1100000
MaxNoOfConcurrentTransactions=327680
NoOfFragmentLogFiles=256
FragmentLogFileSize=32M
SharedGlobalMemory=512M
DiskPageBufferMemory=512M
DiskIoThreadPool=8
[ndb_mgmd]
NodeId=1
hostname=10.142.0.7
datadir=/var/lib/mysql-cluster/mgmt
[ndbd]
NodeId=11
hostname=10.142.0.8
datadir=/var/lib/mysql-cluster/data1
[ndbd]
NodeId=12
hostname=10.142.0.9
datadir=/var/lib/mysql-cluster/data2
[ndbd]
NodeId=13
hostname=10.142.0.10
datadir=/var/lib/mysql-cluster/data3
[ndbd]
NodeId=14
hostname=10.142.0.11
datadir=/var/lib/mysql-cluster/data4
[mysqld]
NodeId=100
所有节点都按预期连接到管理服务器
-- NDB Cluster -- Management Client --
ndb_mgm> show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 4 node(s)
id=11 @10.142.0.8 (mysql-5.6.29 ndb-7.4.11, Nodegroup: 0, *)
id=12 @10.142.0.9 (mysql-5.6.29 ndb-7.4.11, Nodegroup: 0)
id=13 @10.142.0.10 (mysql-5.6.29 ndb-7.4.11, Nodegroup: 1)
id=14 @10.142.0.11 (mysql-5.6.29 ndb-7.4.11, Nodegroup: 1)
[ndb_mgmd(MGM)] 1 node(s)
id=1 @10.142.0.7 (mysql-5.6.29 ndb-7.4.11)
[mysqld(API)] 1 node(s)
id=100 @10.142.0.2 (mysql-5.6.29 ndb-7.4.11)
附加信息:
Create Table: CREATE TABLE `tbl` (
`no` int(11) NOT NULL AUTO_INCREMENT,
`rule_name` varchar(50) DEFAULT NULL,
`ip` varchar(20) DEFAULT NULL,
`detection_time` datetime NOT NULL,
`uri` text,
`site` varchar(500) DEFAULT NULL,
`country` varchar(50) DEFAULT NULL,
`body` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`detection_string` text,
`detection_type` int(11) NOT NULL,
`action` int(11) NOT NULL,
`category` int(10) NOT NULL,
PRIMARY KEY (`no`),
KEY `no` (`no`),
KEY `ip` (`ip`)
) ENGINE=InnoDB AUTO_INCREMENT=21682043 DEFAULT CHARSET=utf8
1 row in set (0.03 sec)
冗余索引。A
PRIMARY KEY
是一个索引,所以不需要多余的KEY no(no)
。(DROPping
这会加快速度。)代理人。
agent
架构中的哪里?它是一个varchar吗?还是枚举?或归一化SMALLINT UNSIGNED
。最后一个会节省空间,从而提高速度,但会使插入复杂化。更好的索引。替换
INDEX(ip)
为INDEX(ip, agent)
。这将加快给定的SELECT
一些。(但我怀疑代理对于给定的 IP 通常是相同的。)国家代码有非常标准的 2 字母国家代码;使用它们而不是笨重的
varchar(50)
.批处理。现在为了真正的加速......批量插入。将它们收集在表、交换表
INSERT..SELECT
等中。 详细信息在此处。这种技术是自我调整的;因此,如果事情变得更慢,他们的行动也会变得更有效率。该链接还解释了如何有效地规范化。调音。
IndexMemory=128M
看起来小得不合理。回到 InnoDB?
我提到的技术非常适合 InnoDB;我对 NDB Cluster 的经验较少。也许你应该回到 InnoDB,我们可以努力让它变得更好?
innodb_buffer_pool_size
应该是 RAM 的 70% 左右。IPv6。附注:IPv4 只需要
VARCHAR(15)
; IPv6 需要(39)
。ip 地址也可以是CHARACTER SET ascii
utf8,而不是 utf8。(这里没有显着的性能优势。)