Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL e NoSQL:aiutami a scegliere quello giusto

Dovresti leggere quanto segue e imparare un po' sui vantaggi di una tabella innodb ben progettata e su come utilizzare al meglio gli indici cluster - disponibile solo con 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/

quindi progetta il tuo sistema qualcosa sulla falsariga del seguente esempio semplificato:

Schema di esempio (semplificato)

Le caratteristiche importanti sono che le tabelle utilizzano il motore innodb e la chiave primaria per la tabella dei thread non è più una singola chiave auto_incrementante ma un composto cluster chiave basata su una combinazione di forum_id e thread_id. es.

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
...

Ogni riga del forum include un contatore chiamato next_thread_id (unsigned int) che viene mantenuto da un trigger e aumenta ogni volta che un thread viene aggiunto a un determinato forum. Ciò significa anche che possiamo archiviare 4 miliardi di thread per forum anziché 4 miliardi di thread in totale se si utilizza una singola chiave primaria auto_increment per 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

Lo svantaggio dell'utilizzo di una chiave composta è che non è più possibile selezionare un thread solo in base a un singolo valore di chiave come segue:

select * from threads where thread_id = y;

devi fare:

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

Tuttavia, il codice dell'applicazione dovrebbe essere a conoscenza di quale forum sta navigando un utente, quindi non è esattamente difficile da implementare:archivia il forum_id attualmente visualizzato in una variabile di sessione o in un campo modulo nascosto ecc...

Ecco lo schema semplificato:

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 ;

Potresti aver notato che ho incluso reply_count come parte della chiave primaria, il che è un po 'strano poiché il composito (forum_id, thread_id) è unico di per sé. Questa è solo un'ottimizzazione dell'indice che consente di risparmiare alcuni I/O quando vengono eseguite query che utilizzano response_count. Si prega di fare riferimento ai 2 link sopra per ulteriori informazioni su questo.

Esempio di query

Sto ancora caricando i dati nelle mie tabelle di esempio e finora ho caricato ca. 500 milioni di righe (la metà del tuo sistema). Quando il processo di caricamento è completo, dovrei aspettarmi di avere circa:

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

Ho deliberatamente fatto in modo che alcuni forum contengano più di 5 milioni di thread, ad esempio il forum 65 ha 15 milioni di thread:

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

Interroga tempi di esecuzione

select sum(next_thread_id) from forums;

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

sotto innodb la somma di next_thread_ids per dare un conteggio totale dei thread è molto più veloce del solito:

select count(*) from threads;

Quanti thread ha il forum 65:

select next_thread_id from forums where forum_id = 65

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

ancora una volta questo è più veloce del solito:

select count(*) from threads where forum_id = 65

Ok ora sappiamo di avere circa 500 milioni di thread finora e il forum 65 ne ha 15 milioni - vediamo come si comporta lo schema :)

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

Mi sembra piuttosto performante, quindi è una singola tabella con oltre 500 milioni di righe (e in crescita) con una query che copre 15 milioni di righe in 0,02 secondi (sotto carico!)

Ulteriori ottimizzazioni

Questi includerebbero:

  • partizionamento per intervallo

  • partizionamento orizzontale

  • buttandogli contro denaro e hardware

ecc...

spero che questa risposta ti sia utile :)