sql >> Base de Datos >  >> RDS >> Mysql

MySQL y NoSQL:ayúdame a elegir el correcto

Debería leer lo siguiente y aprender un poco sobre las ventajas de una tabla innodb bien diseñada y la mejor manera de usar índices agrupados, ¡solo disponible 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/

luego diseñe su sistema algo similar al siguiente ejemplo simplificado:

Esquema de ejemplo (simplificado)

Las características importantes son que las tablas utilizan el motor innodb y la clave principal para la tabla de subprocesos ya no es una única clave de incremento automático, sino una clave agrupada compuesta. clave basada en una combinación de forum_id y thread_id. por ejemplo

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

Cada fila del foro incluye un contador llamado next_thread_id (int sin firmar) que se mantiene mediante un activador y aumenta cada vez que se agrega un hilo a un foro determinado. Esto también significa que podemos almacenar 4000 millones de subprocesos por foro en lugar de 4000 millones de subprocesos en total si usamos una única clave principal de incremento automático para 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

La desventaja de usar una clave compuesta es que ya no puede simplemente seleccionar un hilo por un solo valor de clave de la siguiente manera:

select * from threads where thread_id = y;

tienes que hacer:

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

Sin embargo, el código de su aplicación debe saber en qué foro está navegando un usuario, por lo que no es exactamente difícil de implementar:almacene el forum_id que se ve actualmente en una variable de sesión o en un campo de formulario oculto, etc.

Aquí está el esquema simplificado:

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 ;

Es posible que haya notado que he incluido answer_count como parte de la clave principal, lo cual es un poco extraño ya que el compuesto (forum_id, thread_id) es único en sí mismo. Esta es solo una optimización de índice que ahorra algunas operaciones de E/S cuando se ejecutan consultas que usan answer_count. Consulte los 2 enlaces anteriores para obtener más información al respecto.

Consultas de ejemplo

Todavía estoy cargando datos en mis tablas de ejemplo y hasta ahora tengo cargado aprox. 500 millones de filas (la mitad que su sistema). Cuando se complete el proceso de carga, debo esperar tener aproximadamente:

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

He hecho deliberadamente que algunos de los foros contengan más de 5 millones de hilos, por ejemplo, el foro 65 tiene 15 millones de hilos:

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

Tiempos de ejecución de consultas

select sum(next_thread_id) from forums;

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

en innodb, sumar next_thread_ids para obtener un recuento total de subprocesos es mucho más rápido que lo habitual:

select count(*) from threads;

Cuántos hilos tiene el foro 65:

select next_thread_id from forums where forum_id = 65

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

de nuevo, esto es más rápido que lo habitual:

select count(*) from threads where forum_id = 65

Bien, ahora sabemos que tenemos alrededor de 500 millones de subprocesos hasta el momento y el foro 65 tiene 15 millones de subprocesos. Veamos cómo funciona el esquema :)

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

Me parece bastante eficaz, así que es una sola tabla con más de 500 millones de filas (y creciendo) con una consulta que cubre 15 millones de filas en 0,02 segundos (¡mientras está bajo carga!)

Otras optimizaciones

Estos incluirían:

  • partición por rango

  • fragmentación

  • tirarle dinero y hardware

etc...

espero que encuentres esta respuesta útil :)