私のデータベースに2つのテーブルがあり、現在は何百万もの行があります。選択と挿入が遅くなり、遅くなります。Mysql 5.5テーブルパーティションのユーザーとフレンド
私は私の現在のDbの構造は
CREATE TABLE `user` (
`id` BIGINT(20) NOT NULL,
`name` VARCHAR(255) DEFAULT NULL,
`email` VARCHAR(255) DEFAULT NULL,
`location_id` bigint(20) default NULL,
`updated_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK3DC99772C476E06B` (`location_id`),
CONSTRAINT `FK3DC99772C476E06B` FOREIGN KEY (`location_id`) REFERENCES `places` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
CREATE TABLE `friends` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`user_id` BIGINT(20) DEFAULT NULL,
`friend_id` BIGINT(20) DEFAULT NULL,
`updated_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_friend` (`user_id`,`friend_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
のようなものです、
を春+ + MySQLの5.5を休止し、シャーディングと同様にテーブルを分割し、私のテーブルを分割するというアイデアのように読んを使用しています今私は使用法に基づいて良いと思っているユーザーテーブルのために、より良いパーティション分割を使用する方法をテストしています。
CREATE TABLE `user_partition` (
`id` BIGINT(20) NOT NULL,
`name` VARCHAR(255) DEFAULT NULL,
`email` VARCHAR(255) DEFAULT NULL,
`location_id` bigint(20) default NULL,
`updated_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK3DC99772C476E06B` (`location_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
PARTITION BY HASH(id DIV 100000)
PARTITIONS 30;
私は2つのテーブル内のデータをロードすると結果がsurprizingれた2つのテーブル
DELIMITER //
CREATE PROCEDURE load_partition_table()
BEGIN
DECLARE v INT DEFAULT 0;
WHILE v < 1000000
DO
INSERT INTO user_partition (id,NAME,email)
VALUES (v,CONCAT(v,' name'),CONCAT(v,'@yahoo.com')),
(v+1,CONCAT(v+1,' name'),CONCAT(v+1,'@yahoo.com')),
(v+2,CONCAT(v+2,' name'),CONCAT(v+2,'@yahoo.com')),
(v+3,CONCAT(v+3,' name'),CONCAT(v+3,'@yahoo.com')),
(v+4,CONCAT(v+4,' name'),CONCAT(v+4,'@yahoo.com')),
(v+5,CONCAT(v+5,' name'),CONCAT(v+5,'@yahoo.com')),
(v+6,CONCAT(v+6,' name'),CONCAT(v+6,'@yahoo.com')),
(v+7,CONCAT(v+7,' name'),CONCAT(v+7,'@yahoo.com')),
(v+8,CONCAT(v+8,' name'),CONCAT(v+8,'@yahoo.com')),
(v+9,CONCAT(v+9,' name'),CONCAT(v+9,'@yahoo.com'))
;
SET v = v + 10;
END WHILE;
END
//
CREATE PROCEDURE load_table()
BEGIN
DECLARE v INT DEFAULT 0;
WHILE v < 1000000
DO
INSERT INTO user (id,NAME,email)
VALUES (v,CONCAT(v,' name'),CONCAT(v,'@yahoo.com')),
(v+1,CONCAT(v+1,' name'),CONCAT(v+1,'@yahoo.com')),
(v+2,CONCAT(v+2,' name'),CONCAT(v+2,'@yahoo.com')),
(v+3,CONCAT(v+3,' name'),CONCAT(v+3,'@yahoo.com')),
(v+4,CONCAT(v+4,' name'),CONCAT(v+4,'@yahoo.com')),
(v+5,CONCAT(v+5,' name'),CONCAT(v+5,'@yahoo.com')),
(v+6,CONCAT(v+6,' name'),CONCAT(v+6,'@yahoo.com')),
(v+7,CONCAT(v+7,' name'),CONCAT(v+7,'@yahoo.com')),
(v+8,CONCAT(v+8,' name'),CONCAT(v+8,'@yahoo.com')),
(v+9,CONCAT(v+9,' name'),CONCAT(v+9,'@yahoo.com'))
;
SET v = v + 10;
END WHILE;
END
//
のパフォーマンスをチェックするための手順を作成し、より良い結果を与える非パーティションテーブルで選択/挿入します。
mysql> select count(*) from user_partition;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.40 sec)
mysql> select count(*) from user;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.00 sec)
mysql> call load_table();
Query OK, 10 rows affected (20.31 sec)
mysql> call load_partition_table();
Query OK, 10 rows affected (21.22 sec)
mysql> select * from user where id = 999999;
+--------+-------------+------------------+---------------------+
| id | name | email | updated_time |
+--------+-------------+------------------+---------------------+
| 999999 | 999999 name | [email protected] | 2012-11-27 08:06:54 |
+--------+-------------+------------------+---------------------+
1 row in set (0.00 sec)
mysql> select * from user_no_part where id = 999999;
+--------+-------------+------------------+---------------------+
| id | name | email | updated_time |
+--------+-------------+------------------+---------------------+
| 999999 | 999999 name | [email protected] | 2012-11-27 08:03:14 |
+--------+-------------+------------------+---------------------+
1 row in set (0.00 sec)
ように、2つの質問
1)を挿入するようにuser
テーブルを分割するための最良の方法いただきましたし、また、高速になるとlocation_id
にFOREIGN KEYを削除することは正しい選択しますか?私はパーティションキーの基盤にアクセスする場合のみ、パーティションが良いことがわかります私の場合は、私はidだけでテーブルを読んでみたいです。なぜパーティションテーブルの挿入が遅いのですか?
2)テーブルをパーティション化するには、user_id
のベースですべてのユーザーフレンドを同じパーティションに配置し、常にuser_idを使用してアクセスする必要があります。プライマリキーをfriend.idにドロップするか、プライマリキーにuser_idを追加する必要がありますか?
ポストには、パフォーマンスに大きな違いはありません。 100万レコードを挿入する場合の1秒の差はかなり小さい(約0.5%)。 –
AFAIKはSELECTの速度を上げるために、[indexing](http://dev.mysql.com/doc/refman/5.5/en/mysql-indexes.html)が適切な解決策です。また、[INSERTスピードアップに関するアドバイス](http://dev.mysql.com/doc/refman/5.5/en/insert-speed.html)もあります。メインラインでは、一括挿入が行われています。 –