Могу ли я оптимизировать свою базу данных, разбив одну большую таблицу на множество маленьких? - PullRequest
6 голосов
/ 07 ноября 2010

Предположим, у меня есть одна большая таблица с тремя столбцами: "user_name", "user_property", "value_of_property". Латы также предполагают, что у меня много пользователей (скажем, 100 000) и много свойств (скажем, 10 000). Тогда таблица станет огромной (1 миллиард строк).

Когда я извлекаю информацию из таблицы, мне всегда нужна информация о конкретном пользователе. Итак, я использую, например where user_name='Albert Gates'. Таким образом, каждый раз, когда серверу mysql необходимо проанализировать 1 миллиард строк, чтобы найти те из них, которые содержат «Albert Gates» в качестве имени пользователя.

Не было бы разумно разделить большую таблицу на множество маленьких, соответствующих фиксированным пользователям?

Ответы [ 4 ]

5 голосов
/ 07 ноября 2010

Нет, я не думаю, что это хорошая идея. Лучшим подходом является добавление индекса к столбцу user_name и, возможно, другого индекса на (user_name, user_property) для поиска одного свойства. Тогда базе данных не нужно сканировать все строки - ей просто нужно найти соответствующую запись в индексе, который хранится в B-Tree , что облегчает поиск записи в очень небольшом количестве. времени.

Если ваше приложение все еще работает медленно даже после правильной индексации, иногда может быть хорошей идеей разбить ваших самых больших таблиц.

Еще одна вещь, которую вы могли бы рассмотреть, - это нормализация базы данных, чтобы имя пользователя сохранялось в отдельной таблице и вместо него использовалось целочисленный ключ foriegn. Это может снизить требования к хранилищу и повысить производительность. То же самое может относиться к user_property.

3 голосов
/ 07 ноября 2010

вы должны нормализовать ваш дизайн следующим образом:

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');

С точки зрения производительности кластерный индекс innodb творит чудеса в этом похожем примере (прогон COLD):

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)
2 голосов
/ 07 ноября 2010

Правильная индексация вашей базы данных будет лучшим способом повышения производительности.Однажды у меня был запрос, занимающий полчаса (для большого набора данных, но тем не менее).Затем мы приходим к выводу, что таблицы не имеют индекса.После индексации запрос занял менее 10 секунд.

1 голос
/ 07 ноября 2010

Зачем вам нужна эта структура таблицы.Моя основная проблема заключается в том, что вам придется приводить данные в значение свойства каждый раз, когда вы захотите их использовать.На мой взгляд, это плохо - хранение чисел, так как текст сумасшедший, учитывая, что все равно в двоичном виде.Например, как вы собираетесь иметь обязательные поля?Или поля, которые должны иметь ограничения на основе других полей?Например, дата начала и окончания?

Почему бы просто не иметь свойства в виде полей, а не отношения многие ко многим?

иметь 1 плоскую таблицу.Когда ваши бизнес-правила начинают показывать, что свойства должны быть сгруппированы, вы можете рассмотреть возможность их перемещения в другие таблицы и иметь несколько отношений 1: 0-1 с таблицей пользователей.Но это не нормализация, и это немного ухудшит производительность из-за дополнительного объединения (однако самодокументируемая природа имен таблиц очень поможет любым разработчикам)

Один из способов, которым я регулярно вижу, как производительность базы данных полностью кастрируется, - этоимеющий общий

Id, тип свойства, имя свойства, таблицу значений свойства.

Это действительно ленивый, но исключительно гибкий, но полностью снижающий производительность.На самом деле на новой работе, где производительность плохая, я действительно спрашиваю, есть ли у них таблица с такой структурой - она ​​неизменно становится центральной точкой базы данных и работает медленно.Весь смысл проектирования реляционных баз данных заключается в том, что отношения определяются заранее.Это просто методика, которая направлена ​​на ускорение разработки с огромными затратами на скорость приложения.Кроме того, он сильно полагается на бизнес-логику на уровне приложений, что вовсе не является защитным.В конце концов вы обнаружите, что хотите использовать свойства в ключевой взаимосвязи, которая приводит ко всем видам приведения в соединение, что еще больше снижает производительность.

Если данные имеют отношение 1: 1 с сущностью, то это должно бытьполе на той же таблице.Если ваша таблица достигает более 30 полей в ширину, подумайте о том, чтобы переместить их в другую таблицу , но не называйте это нормализацией, поскольку она не .Это метод, который помогает разработчикам группировать поля вместе за счет производительности, пытаясь помочь в понимании.

Я не знаю, есть ли у mysql эквивалент, но в sqlserver 2008 есть разреженные столбцы - пустые значения не занимают места, Типы данных разреженных столбцов

Я не говорю, что подход EAV всегда неверен, но я думаю, что использование реляционной базы данных для этого подхода, вероятно, не лучший выбор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...