Ho due tabelle nel mio db che hanno milioni di righe ora, la selezione e l'inserimento sta diventando sempre più lento.Mysql 5.5 Tabella partizione utenti e amici
Sto usando la primavera + hibernate MySQL + 5.5 e leggere le sharding così come il partizionamento del tavolo e come l'idea di partizionamento mie tabelle,
mio attuale struttura Db è come
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
Ora sto testando come utilizzare meglio il partizionamento, per la tabella degli utenti che segue penso sia buona per l'utilizzo.
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;
ho creato una procedure per caricare i dati in due tavolo e verificare le prestazioni delle due tabelle
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
//
I risultati sono stati Sorprendente, inserire/selezionare nella tabella delle partizioni non dare risultati migliori.
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)
Così due domanda
1) Che cosa è il modo migliore per partizionare user
tavolo in modo che inseriscono e scelgono anche diventare veloce e la rimozione di chiave esterna sulla location_id
è corretta? So che la partizione può essere buona solo se si accede alla base della chiave di partizione, nel mio caso voglio leggere la tabella solo da id. perché gli inserti sono più lenti nella tabella delle partizioni?
2) Quale è il modo migliore per partizionare la tabella come voglio partizionare gli amici sulle basi di user_id
come si desidera posizionare tutti gli amici degli utenti nella stessa partizione e accedervi sempre utilizzando un id_utente. Devo rilasciare la chiave primaria su friend.id o aggiungere user_id nella chiave primaria?
Il post non mostra alcuna differenza di prestazioni apprezzabile; una sola differenza di inserimento di un milione di record è piuttosto insignificante (~ 0,5%). –
AFAIK per accelerare SELECT, [indicizzazione] (http://dev.mysql.com/doc/refman/5.5/en/mysql-indexes.html) è la soluzione corretta. C'è [qualche consiglio su INSERT speed-up] (http://dev.mysql.com/doc/refman/5.5/en/insert-speed.html), anche la linea principale è quella di fare inserimenti di massa. –