2010-11-07 15 views
6

Supongamos que tengo una gran tabla con tres columnas: "user_name", "user_property", "value_of_property". Lat también asume que tengo muchos usuarios (digamos 100 000) y muchas propiedades (digamos 10 000). Entonces la mesa va a ser enorme (mil millones de filas).¿Puedo optimizar mi base de datos dividiendo una gran tabla en muchas pequeñas?

Cuando extraigo información de la tabla siempre necesito información sobre un usuario en particular. Entonces, uso, por ejemplo, where user_name='Albert Gates'. Entonces, cada vez que el servidor mysql necesita analizar mil millones de líneas para encontrar aquellas que contienen "Albert Gates" como nombre_usuario.

¿No sería inteligente dividir la gran mesa en muchas pequeñas que corresponden a usuarios fijos?

+0

lo que está describiendo se llama partición. En las bases de datos usted diseña su estructura rtable alrededor de sus datos. Configura el hardware para administrar este tipo de problema. Creo que la partición (que es la jerga del servidor sql para lo que estás hablando) es una característica que no está en mysql, o no fue hace 7 años cuando cambié al servidor sql, que sé que sí lo admite. –

+0

@John Nicholas: http://dev.mysql.com/doc/refman/5.1/en/partitioning.html –

+0

coool tyvm;) mysql tiene particiones después de todo –

Respuesta

5

No, no creo que sea una buena idea. Un mejor enfoque es add an index en la columna user_name - y tal vez otro índice en (user_name, user_property) para buscar una sola propiedad. Entonces, la base de datos no necesita escanear todas las filas, solo necesita encontrar la entrada apropiada en el índice que está almacenada en un B-Tree, lo que hace que sea fácil encontrar un registro en muy poco tiempo.

Si su aplicación aún es lenta incluso después de indexar correctamente, a veces puede ser una buena idea para partition sus tablas más grandes.

Otra cosa que podría considerar es normalizar su base de datos para que el nombre_usuario se almacene en una tabla separada y use una clave de clave entera en su lugar. Esto puede reducir los requisitos de almacenamiento y puede aumentar el rendimiento. Lo mismo puede aplicarse a user_property.

+0

la otra ventaja de normalizar user_name y usar su id en otras tablas es que si necesita cambiarlo no tiene que actualizar potencialmente miles de registros y todas sus relaciones. –

3

debe normalizar su diseño de la siguiente manera:

drop table if exists users; 
create table users 
(
user_id int unsigned not null auto_increment primary key, 
username varbinary(32) unique not null 
) 
engine=innodb; 

drop table if exists properties; 
create table properties 
(
property_id smallint unsigned not null auto_increment primary key, 
name varchar(255) unique not null 
) 
engine=innodb; 

drop table if exists user_property_values; 
create table user_property_values 
(
user_id int unsigned not null, 
property_id smallint unsigned not null, 
value varchar(255) not null, 
primary key (user_id, property_id), 
key (property_id) 
) 
engine=innodb; 

insert into users (username) values ('f00'),('bar'),('alpha'),('beta'); 

insert into properties (name) values ('age'),('gender'); 

insert into user_property_values values 
(1,1,'30'),(1,2,'Male'), 
(2,1,'24'),(2,2,'Female'), 
(3,1,'18'), 
(4,1,'26'),(4,2,'Male'); 

Desde la perspectiva del rendimiento del índice innodb clúster funciona de maravilla en este ejemplo similar (de marcha en frío):

select count(*) from product 
count(*) 
======== 
1,000,000 (1M) 

select count(*) from category 
count(*) 
======== 
250,000 (500K) 

select count(*) from product_category 
count(*) 
======== 
125,431,192 (125M) 

select 
c.*, 
p.* 
from 
product_category pc 
inner join category c on pc.cat_id = c.cat_id 
inner join product p on pc.prod_id = p.prod_id 
where 
pc.cat_id = 1001; 
0:00:00.030: Query OK (0.03 secs) 
+0

por favor comente si no vota, de lo contrario solo está demostrando su ignorancia. –

+0

No creo que hayas normalizado nada. ¿Qué ha sido normalizado? ¿Qué orden de normalización es? ¿Qué repetición de datos se ha eliminado? Además (y esto es nit picky, lo siento), ¿dónde vas a almacenar el valor de la propiedad? ¿Realmente quieres que las propiedades tengan una relación de muchos a muchos? Actualmente, cada propiedad se puede compartir entre múltiples usuarios y será muy difícil tener las propiedades requeridas. –

+0

lo siento lo borré mientras reflexioné. –

1

¿Por qué te necesita tener esta estructura de tabla. Mi problema fundamental es que vas a tener que convertir los datos en el valor de la propiedad cada vez que quieras usarla. Eso es malo en mi opinión, también almacenar números ya que el texto es una locura dado que de todos modos es binario. Por ejemplo, ¿cómo vas a tener los campos requeridos? O campos que necesitan tener restricciones basadas en otros campos? Por ejemplo, fecha de inicio y finalización?

¿Por qué no simplemente tener las propiedades como campos en lugar de una relación de muchos a muchos?

tienen 1 mesa plana. Cuando las reglas de su empresa comiencen a mostrar que las propiedades deben agruparse, puede considerar moverlas a otras tablas y tener varias relaciones 1: 0-1 con la tabla de usuarios. Pero esto no es normalización y degradará ligeramente el rendimiento debido a la combinación adicional (sin embargo, la naturaleza autodocumentada de los nombres de tablas ayudará mucho a los desarrolladores)

Una forma en que veo regularmente el rendimiento de Databqase es castrarme por completo al tener una genérico

Id, tipo de propiedad, nombre de la propiedad, tabla de valor de la propiedad.

Esto es realmente flojo pero excepcionalmente flexible pero mata por completo el rendimiento. De hecho, en un nuevo trabajo donde el rendimiento es malo, en realidad pregunto si tienen una tabla con esta estructura: invariablemente se convierte en el punto central de la base de datos y es lenta.El objetivo del diseño de una base de datos relacional es que las relaciones se determinen con anticipación. Esta es simplemente una técnica que tiene como objetivo acelerar el desarrollo a un gran costo para la velocidad de la aplicación. También se basa en la lógica de negocios en la capa de aplicación para comportarse, lo cual no es para nada defensivo. Finalmente, encontrará que desea utilizar propiedades en un relationsip clave que conduce a todo tipo de fundición en la unión, lo que degrada aún más el rendimiento.

Si los datos tienen una relación 1: 1 con una entidad, entonces debería ser un campo en la misma tabla. Si su tabla llega a más de 30 campos de ancho, entonces considere moverlos a otra tabla pero no la llame normalización porque no es. Es una técnica para ayudar a los desarrolladores a agrupar campos a expensas del rendimiento en un intento de ayudar a la comprensión.

No sé si mysql tiene un equivalente pero sqlserver 2008 tiene columnas dispersas - los valores nulos no ocupan espacio. SParse column datatypes

No estoy diciendo que un enfoque de EAV siempre es incorrecto, pero creo que usar una base de datos relacional para este enfoque probablemente no sea la mejor opción.

2

La indexación correcta de su base de datos será la forma número 1 de mejorar el rendimiento. Una vez tuve una consulta de tomar media hora (en un gran conjunto de datos, pero no obstante). Luego llegamos a descubrir que las tablas no tenían índice. Una vez indexado, la consulta tomó menos de 10 segundos.

Cuestiones relacionadas