Сохранение изменений в объектах: является ли MySQL правильным решением?

Я хочу сохранить изменения, которые я делаю в своей таблице "entity". Это должно быть похоже на журнал. В настоящее время он реализуется с помощью этой таблицы в MySQL:

CREATE TABLE `entitychange` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `entity_id` int(10) unsigned NOT NULL,
  `entitytype` enum('STRING_1','STRING_2','SOMEBOOL','SOMEDOUBLE','SOMETIMESTAMP') NOT NULL DEFAULT 'STRING_1',
  `when` TIMESTAMP NOT NULL,
  `value` TEXT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  • entity_id= первичный ключ моей таблицы entity.
  • entitytype= поле, которое было изменено в таблице entity. иногда изменяется только одно поле, иногда несколько. одно изменение = одна строка.
  • value= строковое представление "нового значения" поля.

Пример при изменении поля entity.somedouble от 3 до 2, я запускаю эти запросы:

UPDATE entity SET somedouble = 2 WHERE entity_id = 123;
INSERT INTO entitychange (entity_id,entitytype,value) VALUES (123,'SOMEDOUBLE',2);

Мне нужно select изменить конкретный объект и тип сущности за последние 15 дней. Например: последние изменения с SOMEDOUBLE для entity_id 123 в течение последних 15 дней.

Теперь есть две вещи, которые мне не нравятся:

  • Все данные хранятся как TEXT - хотя большинство (менее 1%) на самом деле не текст, в моем случае большинство значений DOUBLE. Это большая проблема?
  • При вставке таблица становится действительно очень медленной, поскольку в таблице уже 200 миллионов строк. Из-за этого моя загрузка на моем компьютере составляет до 10-15.

Мой вопрос: Как мне адресовать эти два "узких места"? Мне нужно масштабировать.

Мои подходы:

  • Сохраните его следующим образом: http://sqlfiddle.com/#!2/df9d0 (нажмите на просмотр). Сохраните изменения в таблице entitychange, а затем сохраните значение в соответствии с его типом данных в entitychange_[bool|timestamp|double|string]
  • Используйте разбиение на HASH(entity_id) - я думал о ~ 50 разделах.
  • Должен ли я использовать другую систему баз данных, возможно, MongoDB?

Ответ 1

Если бы я столкнулся с проблемой, о которой вы упомянули, я бы разработал таблицу журналов, например, ниже:

  • EntityName: (String) Объект, который обрабатывается. (обязательно)
  • ObjectId: управляемый объект, первичный ключ.
  • FieldName: (String) Имя поля сущности.
  • OldValue: (String) Старое значение поля объекта.
  • NewValue: (String) Новое значение поля объекта.
  • UserCode: уникальный идентификатор пользователя приложения. (Обязательно)
  • TransactionCode: Любая операция, изменяющая объекты, должна иметь уникальный код транзакции (например, GUID) (обязательно),
    В случае обновления объекта, изменяющего несколько полей, этот столбец будет ключевым пунктом для отслеживания всех изменений в обновлении (трансакции)
  • ChangeDate: Дата транзакции. (Обязательно)
  • FieldType: перечисление или текст, показывающий тип поля, например TEXT или Double. (Обязательно)

С помощью этого подхода
Любой объект (таблица) можно проследить
Отчеты будут читабельны
Только изменения будут регистрироваться.
Код транзакции будет ключевым моментом для обнаружения изменений одним действием.

BTW

Store the changes in the entitychange table and then store the value 
according to its datatype in entitychange_[bool|timestamp|double|string]

Не понадобится, в отдельной таблице будут изменения и типы данных

Use partitioning by HASH(entity_id)

Я предпочел бы разбиение на разделы с помощью ChangeDate или создание резервных таблиц для changeDate, которые достаточно стары для резервного копирования и удаления из основной таблицы журналов

Should I use another database system, maybe MongoDB?

Любая база данных поставляется с собственными проблемами и минусами, вы можете использовать проект на любой СУБД. Полезное сравнение основанных на данных данных баз данных, таких как MongoDB можно найти здесь

надеюсь, будет полезно.

Ответ 2

Теперь я думаю, что понимаю, что вам нужно, измененная таблица с историей записей. Это может быть другим способом достижения того же, и вы можете легко сделать несколько быстрых тестов, чтобы убедиться, что он дает вам лучшую производительность, чем ваше текущее решение. Его способ Symfony PHP Framework делает это в Doctrine с плагином Versionable.

Имейте в виду, что есть первичный ключ уникального индекса двух ключей, версии и fk_entity.

Также взгляните на сохраненные значения. Вы сохраните значение 0 в полях, которые не изменились, а измененное значение изменилось.

CREATE TABLE `entity_versionable` (
  `version` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `fk_entity` INT(10) UNSIGNED NOT NULL,
  `str1` VARCHAR(255),
  `str2` VARCHAR(255),
  `bool1` BOOLEAN,
  `double1` DOUBLE,
  `date` TIMESTAMP NOT NULL,
  PRIMARY KEY (`version`,`fk_entity`)
) ENGINE=INNODB DEFAULT CHARSET=latin1;


INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, DATE)
VALUES ("1", "a1", "0", "0", "0", "2013-06-02 17:13:16");
INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, DATE)
VALUES ("1", "a2", "0", "0", "0", "2013-06-11 17:13:12");
INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, DATE)
VALUES ("1", "0", "b1", "0", "0", "2013-06-11 17:13:21");
INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, DATE)
VALUES ("1", "0", "b2", "0", "0", "2013-06-11 17:13:42");
INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, DATE)
VALUES ("1", "0", "0", "1", "0", "2013-06-16 17:19:31");

/*Another example*/
INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, DATE)
VALUES ("1", "a1", "b1", "0", "0", CURRENT_TIMESTAMP);


SELECT * FROM `entity_versionable` t WHERE 
(
    (t.`fk_entity`="1") AND 
    (t.`date` >= (CURDATE() - INTERVAL 15 DAY))
);


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

Ответ 3

Здесь есть две основные проблемы:

  • Как эффективно хранить данные, т.е. занимать меньше места и быть в удобном для использования формате.

2-3. Управление большой таблицей: архивирование, простота резервного копирования и восстановления

2-3. Оптимизация производительности: быстрее вставляет и выбирает

Эффективное хранение данных

  • value. Я бы предложил сделать это VARCHAR (N). Причины:

    • Использование N < 255 будет сохранять 1 байт на строку только из-за типа данных.
    • Использование других типов данных для этой записи: фиксированные типы используют пространство независимо от значения, и обычно это будет 8 байт на строку (datetime, long integer, char (8)) и другие переменные типы данных слишком велики для это поле.
    • Также тип данных TEXT приводит к штрафам за производительность: (from manaul on BLOB и текстовые типы данных)

Экземпляры столбцов TEXT в результате запроса, обрабатываемого с использованием временной таблицы, заставляют сервер использовать таблицу на диске, а не в памяти, потому что механизм хранения MEMORY не поддерживает эти типы данных. Использование диска приводит к снижению производительности, поэтому включите столбцы BLOB или TEXT в результат запроса, только если они действительно необходимы. Например, избегайте использования SELECT *, который выбирает все столбцы.

Каждое значение BLOB или TEXT представлено внутри отдельно выделенным объектом. Это отличается от всех других типов данных, для которых хранение выделяется один раз за столбец при открытии таблицы.

В основном TEXT предназначен для хранения больших строк и составления текста, тогда как VARCHAR() предназначен для относительно коротких строк.

  • id. (обновлено, благодаря @steve) Я согласен, что это поле не содержит никакой полезной информации. Используйте 3 столбца для вашего первичного ключа: entity_id и entitype и when. TIMESTAMP будет вам очень хорошо, что дубликатов не будет. Также такие же столбцы будут использоваться для разделения/подсекции.

Управление таблицами Существует два основных варианта: таблицы MERGE и разделение. Механизм хранения MERGE основан на My_ISAM, который постепенно уменьшается, насколько я понимаю. Вот некоторые сведения о [MERGE Storage Engine]. 2

Основным инструментом является разделение и оно обеспечивает два основных преимущества: 1. Переключение раздела (которое часто является мгновенной операцией на большом фрагменте данных) и сценарием качения: вставляйте новые данные в одну таблицу и затем мгновенно переключайте их все в таблицу архива. 2. Хранение данных в отсортированном порядке, что позволяет обрезку разделов - запрос только тех разделов, которые содержат необходимые данные. MySQL позволяет подсегментации группировать данные дальше.

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

Количество разделов зависит от того, насколько вы хотите, чтобы файл db для этого раздела был. Количество подразделений зависит от количества ядер, поэтому каждое ядро ​​может искать свой собственный раздел, подсетей N-1 должны быть в порядке, поэтому 1 ядро ​​может выполнять общую координационную работу.

Оптимизация

Вставка:

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

  • Измените TEXT на Varchar - требуется некоторое напряжение от db engine

  • Минимальные блокировки журналов и таблиц могут помочь, но не часто можно использовать

Selects:

  • TEXT to Varchar должен определенно улучшить ситуацию.

  • Имейте текущую таблицу с последними данными - последние 15 дней, затем перейдите в архив через переключение разделов. Здесь у вас есть возможность разделить таблицу, отличную от таблицы архива (например, по дате сначала, затем entity_id), и изменить способ разбиения на разделы путем перемещения небольшого (1 дня) данных в временную таблицу и изменения его разбиения.

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

И что касается вашего третьего вопроса, я не вижу, как использование MongoDB будет особенно полезно для этой ситуации.

Ответ 4

Это называется временная база данных, и исследователи изо всех сил старались хранить и запрашивать временные данные более 20 лет.

Попытка хранить данные EAV по мере того, как вы делаете, неэффективна, поскольку хранение числовых данных в столбце TEXT использует много места, и ваша таблица становится все длиннее и длиннее, как вы обнаружили.

Другая опция, которая иногда называется Шестой нормальной формой (хотя существует несколько несвязанных определений для 6NF), заключается в хранении дополнительной таблицы для хранения ревизий для каждого столбца, который вы хотите отслеживать временно. Это похоже на решение, поставленное с помощью ответа @xtrm, но ему не нужно хранить избыточные копии столбцов, которые не изменились. Но это приводит к взрыву в количестве таблиц.

Я начал читать о Anchor Modeling, который promises обрабатывает временные изменения как структуры, так и содержимого. Но я этого недостаточно понимаю, чтобы объяснить это еще. Я просто свяжусь с ним, и, возможно, это будет полезно для вас.

Вот несколько книг, в которых обсуждаются временные базы данных:

Ответ 5

Сохранение целого числа в столбце TEXT - это не-go! TEXT является самым дорогим типом.

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

CREATE TABLE entitychange_somestring (
    entity_id INT NOT NULL PRIMARY KEY,
    ts TIMESTAMP NOT NULL,
    newvalue VARCHAR(50) NOT NULL, -- same type as entity.somestring
    KEY(entity_id, ts)
) ENGINE=MyISAM;

Разделите их, действительно.

Примечание. Я рекомендую использовать движок MyISAM. Вам не нужны транзакции для этой (эти) неограниченной таблицы вставки только для вставки.

Ответ 6

Почему INSERTing так медленно, и что вы можете сделать, чтобы сделать это быстрее.

Это то, на что я бы посмотрел (и примерно в том порядке, в котором я бы работал с ними):

  • Создание нового идентификатора AUTO_INCREMENT и вставка его в первичный ключ требует блокировки (в InnoDB есть специальная блокировка AUTO-INC, которая удерживается до тех пор, пока оператор не закончит работу, эффективно действуя как блокировка таблицы в вашем сценарий). Обычно это не проблема, так как это относительно быстрая операция, но, с другой стороны, при значении нагрузки (Unix) от 10 до 15 у вас, вероятно, будут процессы, ожидающие освобождения этой блокировки. Из информации, которую вы предоставляете, я не вижу никакого использования в вашем суррогатном ключе "id". Посмотрите, может ли падение столбца значительно повлиять на производительность. (BTW, нет правила, чтобы таблица нуждалась в первичном ключе. Если у вас ее нет, это прекрасно)

  • InnoDB может быть относительно дорогим для INSERT. Это компромисс, который позволяет использовать дополнительные функции, такие как транзакции, и может или не может повлиять на вас. Поскольку все ваши действия являются атомарными, я не вижу необходимости в транзакциях. Тем не менее, попробуйте MyISAM. Примечание. MyISAM обычно является плохим выбором для огромных таблиц, поскольку он поддерживает только блокировку таблицы, а не блокировку уровня записи, но поддерживает параллельные вставки, так что это может быть выбор здесь (особенно если вы сбросите первичный ключ, см. выше)

  • Вы можете играть с параметрами движка базы данных. У обоих InnoDB и MyISAM есть варианты, которые вы могли бы изменить. Некоторые из них влияют на то, как данные TEXT фактически хранятся, другие имеют более широкую функцию. Один из них вы должны посмотреть на innodb_flush_log_at_trx_commit.

  • Столбцы TEXT относительно дороги, если (и только если) имеют значения, отличные от NULL. В настоящее время вы сохраняете все значения в столбце TEXT. Стоит дать следующую попытку: добавьте дополнительные поля value_int и value_double в таблицу и сохраните эти значения в соответствующем столбце. Да, это избавит от лишнего места, но может быть быстрее - но это будет во многом зависеть от механизма хранения базы данных и его настроек. Обратите внимание, что многое, что люди думают о производительности столбца TEXT, неверно. (См. мой ответ на связанный с ним вопрос о VARCHAR vs TEXT)

  • Вы предложили распространить информацию более чем на одну таблицу. Это только хорошая идея, если ваши таблицы полностью независимы друг от друга. В противном случае у вас будет больше одной операции INSERT для любых изменений, и вы, скорее всего, сделаете намного хуже. Хотя нормализация данных обычно хороша (tm), она, вероятно, повредит производительность здесь.

Что вы можете сделать для быстрого запуска SELECT

  • Правильные клавиши. И правильные ключи. И на всякий случай я забыл упомянуть: правильные ключи. Вы не указываете подробно, как выглядят ваши выделения, но я предполагаю, что они похожи на "SELECT * FROM entitychange WHERE entity_id = 123 AND ts > ...". Для быстрого выполнения этой операции должен быть достаточно одного составного индекса для entity_id и ts. Поскольку индекс должен обновляться с каждым INSERT, возможно, стоит попробовать производительность как entity_id, ts, так и ts, entity_id: это может иметь значение.

  • Разметка. Я бы даже не поднял этот вопрос, если бы не спросил в вашем вопросе. Вы не говорите, почему вы хотите разбить таблицу. По производительности это обычно не имеет значения, при условии, что у вас есть соответствующие ключи. Существуют некоторые конкретные настройки, которые могут повысить производительность, но для этого вам потребуется правильная настройка оборудования. Если вы решите разбить свою таблицу, подумайте об этом с помощью либо entity_id, либо столбца TIMESTAMP. Используя временную метку, вы можете получить систему архивирования с более старыми данными, которые будут помещены в архивный диск. Однако такая система разбиения потребует некоторого обслуживания (добавления разделов с течением времени).

Мне кажется, что вы не так обеспокоены производительностью запросов, как об исходной скорости вставки, поэтому я не буду вдаваться в подробности о производительности SELECT. Если это вас интересует, предоставьте более подробную информацию.

Ответ 7

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

Рекомендации, которые мы здесь видели, действительно хороши, и вы наверняка заметите значительное улучшение скорости, используя предопределенный тип VARCHAR с размером вместо TEXT. Однако вы могли бы получить скорость, я бы посоветовал не использовать MyISAM для обеспечения целостности данных, оставаясь с InnoDB.

ИСПЫТАНИЕ:

1. Таблица настроек и INSERT 200 миллионов данных:

CREATE TABLE `entity_versionable` (
  `version` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `fk_entity` INT(10) UNSIGNED NOT NULL,
  `str1` VARCHAR(255) DEFAULT NULL,
  `str2` VARCHAR(255) DEFAULT NULL,
  `bool1` TINYINT(1) DEFAULT NULL,
  `double1` DOUBLE DEFAULT NULL,
  `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`version`,`fk_entity`)
) ENGINE=INNODB AUTO_INCREMENT=230297534 DEFAULT CHARSET=latin1

Чтобы вставить +200 миллионов строк за 35 минут в таблицу, проверьте мой другой вопрос, где peterm ответил на один из лучшие способы заполнения таблицы. Он отлично работает.

Выполните следующий запрос 2 раза, чтобы вставить 200 миллионов строк без случайных данных (каждый раз изменять данные для вставки случайных данных):

INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, DATE)
SELECT 1, 'a1', 238, 2, 524627, '2013-06-16 14:42:25'
FROM
(
    SELECT a.N + b.N * 10 + c.N * 100 + d.N * 1000 + e.N * 10000 + f.N * 100000 + g.N * 1000000 + h.N * 10000000 + 1 N FROM 
     (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
    ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
    ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) c
    ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) d
    ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) e
    ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) f
    ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) g
    ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) h
) t;


* Поскольку у вас уже есть исходная таблица с 200 миллионами строк реальных случайных данных, вам, скорее всего, не понадобится ее заполнять, просто экспортируйте данные и схему таблицы и импортируйте их в новую таблицу тестирования с той же схемой. Таким образом, вы сделаете тесты в новой таблице с вашими реальными данными, а улучшения, которые вы получите, также будут работать для оригинальной.

2. ALTER новый тестовый стол для производительности (или используйте мой пример выше на шаге 1, чтобы получить лучшие результаты). После этого у нас есть новая таблица тестовых таблиц и заполнены случайными данными, мы должны проверить вышеприведенные рекомендации, а ALTER таблицу ускорить ее:

  • Измените TEXT на VARCHAR (255).
  • Выберите и сделайте хороший первичный ключ с уникальным индексом с двумя или тремя колонны. Тест с автоинкрементацией версии и fk_entity в первом тест.
  • При необходимости разделите свою таблицу и проверьте, улучшает ли она скорость. я советовал бы не разбивать его в своих первых тестах, чтобы проверьте реальное увеличение производительности за счет изменения типов данных и mysql конфигурации. Проверьте следующую ссылку для раздела и советы по улучшению.
  • Оптимизируйте и восстановите таблицу. Индекс будет сделан снова и будет скорость поиска много:

ОПТИМИЗАЦИЯ ТАБЛИЦЫ test. entity_versionable;
REPAIR TABLE test. entity_versionable;

* Сделайте script, чтобы выполнить оптимизацию и поддерживать ваш индекс в актуальном состоянии, запуская его каждую ночь.


3. Улучшите конфигурацию MySQL и оборудования, внимательно прочитав следующие темы. Они заслуживают внимания, и я уверен, что вы получите лучшие результаты.

  • Легко улучшайте конфигурацию жесткого диска вашей базы данных немного денег: если возможно, используйте SSD для своей основной базы данных MySQL и
    автономный механический жесткий диск для целей резервного копирования. Установка журналов MySQL для сохранения на другом третьем жестком диске для улучшения скорости в вашем Вставки. (Не забудьте дефрагментировать механические жесткие диски после некоторых недель).
  • Ссылки на производительность: общие и множественные ядра, конфигурация, оптимизация IO, Debiancores, лучший конфигурация, config 48gb ram..
  • Профилирование SQL-запроса: Как профилировать запрос, Проверить возможное узкое место в запросе < br/" >
  • MySQL очень интенсивно использует память, использует память CL7 DDR3 с низкой задержкой, если возможное. Немного не по теме, но если ваши системные данные имеют решающее значение, вы можете искать память ECC, однако это дорого.


4. Наконец, проверяет ваши ВСТАВКИ и ПОИСКЫ в тестовой таблице. Im мои тесты с +200 миллионов случайных данных с приведенной выше схемой таблицы, он проводит 0,001 секунд для INSERT новой строки и около 2 минут для поиска и SELECT 100 миллион строк. И, тем не менее, его единственный тест и, кажется, хорошие результаты:)


5. Моя конфигурация системы:

  • База данных:MySQL 5.6.10 База данных InnoDB (тест).
  • Процессор: AMD Phenom II 1090T X6, 3910 МГц каждый ядро.
  • ОЗУ: 16 ГБ DDR3 1600Mhz CL8.
  • HD: Windows 7 64 бит SP1 в SSD, mySQL, установленный в SSD, записывается на механическом жестком диске.
    Вероятно, мы должны получить лучшие результаты, если один из последних Intel i5 или i7 легко разгоняется до 4500 МГц +, поскольку MySQL использует только одно ядро ​​для одного SQL. Чем выше скорость ядра, тем быстрее он будет выполнен.


6. Подробнее о MySQL:
O'Reilly High Performance MySQL
MySQL Оптимизация операторов SQL


7. Использование другой базы данных: MongoDB или Redis будет идеальным для этого случая и, вероятно, намного быстрее, чем MySQL. Оба очень легко узнать, и у обоих есть свои преимущества:
- MongoDB: Рост файла журнала MongoDB

Redis

Я бы окончательно пошел за Redis. Если вы узнаете, как сохранить журнал в Redis, это будет лучший способ управлять журналом с безумно высокой скоростью: redis для ведения журнала
Имейте в виду следующие советы, если вы используете Redis:

  • Redis скомпилирован в C и хранится в памяти, имеет несколько разных методы автоматического сохранения информации на диск (настойчивость), вам, вероятно, не придется беспокоиться об этом. (в случае бедствия сценарий, вы закончите потерять около 1 секунды регистрации).

  • Redis используется во многих сайтах, которые управляют терабайтами данных, есть много способов справиться с этим безумным количеством информации и это означает, что он защищен (используется здесь в stackoverflow, blizzard, twitter, youporn..)

  • Так как ваш журнал будет очень большим, ему нужно будет поместиться в память в чтобы получить скорость без доступа к жесткому диску. Вы можете сохранять различные журналы для разных дат и устанавливать только некоторые из них в Память. В случае достижения предела памяти у вас не будет никаких ошибок, и все будет работать отлично, но для получения дополнительной информации просмотрите Redis Faqs.

  • Я полностью уверен, что Redis будет намного быстрее для этой цели, чем MySQL. Вам нужно будет узнать, как играть с lists и sets для обновления данных и запроса/поиска данных. Если вам могут потребоваться действительно расширенные поиски запросов, вы должны пойти с MongoDB, но в этом случае простые поиски даты будут идеальными для Redis.

Хорошая статья Redis в Блог Instagram.

Ответ 8

На работе у нас есть logtables практически для каждой таблицы из-за условий клиента (финансовый сектор).

Мы сделали это так: две таблицы ( "нормальная" таблица и таблица журналов), а затем триггеры на вставке/обновлении/удалении нормальной таблицы, в которой хранится ключевое слово (I, U, D) и старая запись (при обновлении, удалении) или новый (вставить) внутри журнала

У нас есть обе таблицы в той же схеме базы данных