MySQL. Лучше (производительность) иметь одну таблицу из 1M записей или 10 таблиц по 100K записей в каждой? - PullRequest
3 голосов
/ 16 апреля 2011

Об этом можно спросить раньше, но в любом случае вот такая ситуация.

У меня есть одна большая таблица (на MySQL с использованием InnoDB), которая в основном представляет собой огромный журнал, никаких реляционных вещей.

3 поля: Customer_ID, TimeStamp, Log_Data (который представляет собой крошечный текст, такой как "Visited Front Webpage" или "Logged In").

Поскольку я регистрирую активность клиентов на веб-странице, которая принимает около 10 000 пользователей в день, эта таблица довольно быстро растет.

В определенный момент я хотел узнать, сколько клиентов на самом деле что-то делали на сайте.

Итак, я запускаю следующий запрос «SELECT DISTINCT Customer_ID FROM table;», и я начал замечать, что по мере увеличения таблицы запрос занимает больше времени, что совершенно нормально и вполне ожидаемо. В один момент времени запрос начал занимать более 5 минут.

Я хотел найти более быстрый путь, поэтому я попробовал это. Допустим, я работаю с таблицей с 1 миллионом строк. Я начал с того, что разделил эту таблицу на 10 таблиц, по 100 тысяч записей каждая. Затем я запускаю «SELECT DISTINCT Customer_ID FROM table;» на каждом столе, и со всеми результатами я просто 'сортировать | uniq | wc 'их в командной строке и получить тот же результат.

Удивительно, но этот метод занял меньше половины времени, чем другой.

Я в значительной степени отвечал на вопрос сам, 10 * 100K таблиц быстрее чем 1 * 1M таблицы, НО, может быть, я делаю что-то не так, может быть, это больше проблема настройки производительности или чего-то еще, потому что таблицы должны быть разработаны хорошо выполнять независимо от их размера.

Дайте мне знать, что вы думаете.

Спасибо за чтение.

ОБНОВЛЕНИЕ: Вот как я создаю свою таблицу:

CREATE TABLE `mydb`.`mytable` (
 `Customer_ID` BIGINT( 20 ) UNSIGNED NOT NULL,
 `unix_time` INT( 10 ) UNSIGNED NOT NULL,
 `data` TINYTEXT NOT NULL,
KEY `fb_uid` ( `fb_uid` )
) ENGINE = INNODB DEFAULT CHARSET = utf8;

Ответы [ 4 ]

2 голосов
/ 17 апреля 2011

Вам нужен индекс, который начинается с Customer_ID, чтобы ваш запрос был быстрым. Если у вас есть индекс, который просто содержит его, он не сможет использовать его оптимально. Вот как вы можете его создать:

CREATE INDEX idx_cid ON table (Customer_ID)

Также вы можете получить свой счет прямо из базы данных:

SELECT COUNT(DISTINCT(Customer_ID)) FROM table

Если вы когда-нибудь захотите сузить интервал времени, вам понадобится составной индекс:

CREATE INDEX idx_ts_cid ON table (TimeStamp, Customer_ID)

Тогда запрос будет примерно таким за последний месяц:

SELECT COUNT(DISTINCT(Customer_ID)) FROM table
WHERE TimeStamp BETWEEN "2011-03-01" AND "2011-04-01"
2 голосов
/ 16 апреля 2011

Несмотря на то, что ваше решение 100K * 10 действительно ускоряет запрос, звучит сложно, и, вероятно, это не лучший подход.

"таблицы должны быть спроектированы так, чтобы они работали независимо от их размера"

Вы должны понимать, что это не может быть правдой, когда таблицы становятся слишком большими для используемого вами механизма БД.

Так что вы можете сделать?Решение, вероятно, касается типов запросов, которые вы запускаете для этих данных.

  • Является ли запрос выше только того, который использует эти данные?
  • Если нет, какие другие запросы выполняются на этомтаблица?

Одно из основных правил здесь - не хранить данные, которые вам не понадобятся.Другой способ - хранить данные так, чтобы их было легко запрашивать. Даже если вам нужны строки в 1 млн необработанных данных, вы все равно можете хранить некоторые агрегированные данные (или метаданные) в другой таблице, например, в таблице уникальных идентификаторов customer_id.день, который рассчитывается в конце дня.

1 голос
/ 17 апреля 2011

Чтобы добавить к остальным, так как вы сказали, что не делаете никаких «модных реляционных вещей», вы также можете рассмотреть возможность использования решения для базы данных, ориентированного на массивные наборы данных (и простые таблицы).MongoDB является одним из примеров.

Я должен добавить, что это имеет смысл только в том случае, если остальная часть вашей схемы базы данных также очень большая и нереляционная:)

0 голосов
/ 16 апреля 2011

Кажется, у вас нет индекса для поля user_id или у одного пользователя много строк, например 40000 строк из миллиона.

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