Mysql
 sql >> Base de données >  >> RDS >> Mysql

MySQL et NoSQL :aidez-moi à choisir le bon

Vous devriez lire ce qui suit et en apprendre un peu plus sur les avantages d'une table innodb bien conçue et sur la meilleure façon d'utiliser les index clusterisés - uniquement disponible avec innodb !

http://dev.mysql.com/doc /refman/5.0/en/innodb-index-types.html

http://www. xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/

puis concevez votre système en suivant les lignes de l'exemple simplifié suivant :

Exemple de schéma (simplifié)

Les caractéristiques importantes sont que les tables utilisent le moteur innodb et que la clé primaire de la table des threads n'est plus une seule clé d'auto_incrémentation mais une clé composite cluster clé basée sur une combinaison de forum_id et thread_id. ex.

threads - primary key (forum_id, thread_id)

forum_id    thread_id
========    =========
1                   1
1                   2
1                   3
1                 ...
1             2058300  
2                   1
2                   2
2                   3
2                  ...
2              2352141
...

Chaque ligne de forum comprend un compteur appelé next_thread_id (unsigned int) qui est maintenu par un déclencheur et s'incrémente à chaque fois qu'un fil est ajouté à un forum donné. Cela signifie également que nous pouvons stocker 4 milliards de threads par forum plutôt que 4 milliards de threads au total si nous utilisions une seule clé primaire auto_increment pour thread_id.

forum_id    title   next_thread_id
========    =====   ==============
1          forum 1        2058300
2          forum 2        2352141
3          forum 3        2482805
4          forum 4        3740957
...
64        forum 64       3243097
65        forum 65      15000000 -- ooh a big one
66        forum 66       5038900
67        forum 67       4449764
...
247      forum 247            0 -- still loading data for half the forums !
248      forum 248            0
249      forum 249            0
250      forum 250            0

L'inconvénient d'utiliser une clé composite est que vous ne pouvez plus simplement sélectionner un thread par une seule valeur de clé comme suit :

select * from threads where thread_id = y;

vous devez faire :

select * from threads where forum_id = x and thread_id = y;

Cependant, votre code d'application doit savoir sur quel forum un utilisateur navigue, ce n'est donc pas vraiment difficile à mettre en œuvre - stockez le forum_id actuellement affiché dans une variable de session ou un champ de formulaire caché, etc.

Voici le schéma simplifié :

drop table if exists forums;
create table forums
(
forum_id smallint unsigned not null auto_increment primary key,
title varchar(255) unique not null,
next_thread_id int unsigned not null default 0 -- count of threads in each forum
)engine=innodb;


drop table if exists threads;
create table threads
(
forum_id smallint unsigned not null,
thread_id int unsigned not null default 0,
reply_count int unsigned not null default 0,
hash char(32) not null,
created_date datetime not null,
primary key (forum_id, thread_id, reply_count) -- composite clustered index
)engine=innodb;

delimiter #

create trigger threads_before_ins_trig before insert on threads
for each row
begin
declare v_id int unsigned default 0;

  select next_thread_id + 1 into v_id from forums where forum_id = new.forum_id;
  set new.thread_id = v_id;
  update forums set next_thread_id = v_id where forum_id = new.forum_id;
end#

delimiter ;

Vous avez peut-être remarqué que j'ai inclus reply_count dans la clé primaire, ce qui est un peu étrange car le composite (forum_id, thread_id) est unique en soi. Il s'agit simplement d'une optimisation d'index qui permet d'économiser des E/S lors de l'exécution de requêtes utilisant reply_count. Veuillez vous référer aux 2 liens ci-dessus pour plus d'informations à ce sujet.

Exemples de requêtes

Je charge toujours des données dans mes exemples de tables et jusqu'à présent, j'ai chargé env. 500 millions de lignes (moitié moins que votre système). Lorsque le processus de chargement est terminé, je devrais m'attendre à avoir environ :

250 forums * 5 million threads = 1250 000 000 (1.2 billion rows)

J'ai délibérément fait en sorte que certains forums contiennent plus de 5 millions de discussions, par exemple, le forum 65 a 15 millions de discussions :

forum_id    title   next_thread_id
========    =====   ==============
65        forum 65      15000000 -- ooh a big one

Exécutions de requêtes

select sum(next_thread_id) from forums;

sum(next_thread_id)
===================
539,155,433 (500 million threads so far and still growing...)

sous innodb, additionner les next_thread_ids pour donner un nombre total de threads est beaucoup plus rapide que d'habitude :

select count(*) from threads;

Combien de discussions le forum 65 a-t-il :

select next_thread_id from forums where forum_id = 65

next_thread_id
==============
15,000,000 (15 million)

encore une fois c'est plus rapide que d'habitude :

select count(*) from threads where forum_id = 65

Ok maintenant nous savons que nous avons environ 500 millions de threads jusqu'à présent et que le forum 65 a 15 millions de threads - voyons comment le schéma fonctionne :)

select forum_id, thread_id from threads where forum_id = 65 and reply_count > 64 order by thread_id desc limit 32;

runtime = 0.022 secs

select forum_id, thread_id from threads where forum_id = 65 and reply_count > 1 order by thread_id desc limit 10000, 100;

runtime = 0.027 secs

Cela me semble assez performant - c'est donc une seule table avec plus de 500 millions de lignes (et en croissance) avec une requête qui couvre 15 millions de lignes en 0,02 seconde (en charge !)

Autres optimisations

Ceux-ci incluraient :

  • partitionnement par plage

  • partitionnement

  • y jeter de l'argent et du matériel

etc...

j'espère que cette réponse vous sera utile :)