これが私の状況です:
10Gを超えるWebログ(約3,000万行)を取得し、主にさまざまな条件で検索しました。
例えば。:
select * from tbl
where ip = '123.123.12.3'
and agent = 'mozillar'
and body like '%script%'
データが大きくなるにつれて、単純なクエリは数分かかるので、MySQLクラスターで分散データベースを作成しようとしています。
GoogleクラウドVM上に1つの管理サーバー、1つのSQL(api)サーバー、および4つのデータノードを構築しました。各インスタンスに2つのCPUと8 GBがあります。
問題:
.sqlファイルからデータを復元しようとすると、各挿入ステートメントに約2〜3秒かかります。
3秒* 30m行= FOREVER!
選択クエリにも失望しました。通常のInnoDBのほぼ100倍の時間がかかります。
私は何か間違ったことをしていますか?
私の目的に適した解決策はありますか?
config.ini
[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)
冗長なインデックス。_PRIMARY KEY
_はインデックスなので、冗長なKEY no(no)
は必要ありません。 (DROPping
これにより、処理が少し速くなります。)
Agent。スキーマのagent
はどこにありますか? varcharですか?または列挙型?または正規化された_SMALLINT UNSIGNED
_。最後のものはスペースを節約するため、速度は向上しますが、挿入が複雑になります。
より良いインデックス。INDEX(ip)
をINDEX(ip, agent)
で置き換えます。これは与えられたSELECT
をスピードアップします。 (しかし、エージェントは通常、指定されたIPで同じであると思います。)
国コード非常に標準的な2文字の国コードがあります。かさばるvarchar(50)
の代わりに使用してください。
バッチ処理。とりあえず本当のスピードアップ...インサートをバッチ処理します。それらをテーブルに収集し、テーブルを交換し、_INSERT..SELECT
_など 詳細はこちら 。その手法は自動調整です。物事が遅くなると、彼らの行動もより効率的になります。そのリンクは、効率的に正規化する方法も説明しています。
チューニング。_IndexMemory=128M
_は、不当に小さいようです。
InnoDBに戻りますか?
選択クエリも私を失望させました、それは通常のInnoDBよりもほぼ100倍長くかかります。
私が述べたテクニックはInnoDBのために十分に調整されています。 MySQL Clusterの経験が少ない。たぶん、あなたはInnoDBに戻ったほうがいいでしょう。 _innodb_buffer_pool_size
_はRAMの約70%にする必要があります。
IPv6。補足:IPv4にはVARCHAR(15)
のみが必要です。 IPv6には_(39)
_が必要です。また、IPアドレスは、utf8ではなく_CHARACTER SET ascii
_でもかまいません。 (ここではパフォーマンス上の大きなメリットはありません。)