Как решить медлительность журнала с или без NoSql - PullRequest
3 голосов
/ 09 января 2012

У меня проблема со скоростью поиска в журнале и размером диска.Он очень большой, имеет около 220 миллионов строк и 25-гигабайтный диск, и для извлечения некоторых выборок требуется несколько минут.

Как это работает?Журнал сохраняется в базе данных с использованием Sql Anywhere, в настоящее время версия 9 и вскоре будет перенесена на 11 (мы попытались 12, но из-за некоторых драйверов и некоторых проблем мы вернулись к 11).

Журнал состоит из двух таблиц (имя изменено на английский, чтобы люди могли его понять):

LogTable

Id, DateTime, User, Url, Actionи TableName. Действие - это то, что использовалось: вставка / удаление / обновление TableName - какая таблица в базе данных была затронута.

LogTableFields

Id, LogTable_Id, FieldName,NewValue, OldValue. LogTable_Id - это внешний ключ от LogTable.FieldName - это поле таблицы из БД.

Важно отметить, что NewValue и OldValue являются типом varchar.Потому что записываются все виды полей из других таблиц (datetime, int и т. Д.).

Почему это было сделано таким образом? Поскольку мы должны записать все важные данные.Система создана для Институционального департамента дорожного движения (я не знаю, написано ли это так на должном английском языке, но теперь вы можете понять, о чем это), и иногда они требуют какой-то случайный отчет.

До сих пор мы делали наш отчет просто с помощью выбора SQL.Однако это займет несколько минут, даже если дата и время отфильтрованы.Не стоит и жаловаться, когда это не часто запрашивают.

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

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

Некоторые идеи, предложенные до сих пор:

Идея 1: Iсделал некоторые исследования, и мне сказали работать с NoSql, используя CouchDB .Но то, что я читаю, кажется, что NoSql не является решением моей проблемы.Я не могу поспорить, почему из-за отсутствия опыта в этом.

Идея 2: Физически отделить таблицы журналов от базы данных или от машины.

Идея3: Создайте зеркало из каждой таблицы с полем версии для ведения истории.

Я бы хотел, чтобы максимизация или изменение архитектуры происходило в случае необходимости.

Ответы [ 2 ]

1 голос
/ 18 января 2012

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

Например, ограничение вашего запроса определенным диапазоном DateTime не поможет вообще, если у вас нет индекса DateTime. Без индекса базе данных по-прежнему нужно дотронуться почти до всех 25 ГБ данных, чтобы найти несколько строк в нужном временном диапазоне. Но с помощью индекса он может быстро идентифицировать несколько строк, находящихся в диапазоне времени, о котором вы заботитесь.

В общем, вы всегда должны спрашивать свою базу данных, какой план она использует для выполнения запроса, который занимает слишком много времени. Я не особенно знаком с Sql Anywhere, но я знаю, что у него есть Plan Viewer, который может это сделать. Вы хотите идентифицировать большие последовательные сканы и вместо этого ставить индексы в эти поля.

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

1 голос
/ 14 января 2012

Это похоже на довольно стандартную таблицу аудита.Я не уверен, что вам нужно перейти к решению NoSQL для этого.Большинство строк RDBM будет удобно обрабатывать 220 миллионов строк.

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

Если бы вы использовали что-то вроде MS SQL, вы могли бы создать единую плоскую таблицу для регистрации производительности, а затем построить поверх нее простой куб служб Analysis Services.

Другой вариант - простооптимизировать для отчетов, предполагая, что вы можете поддерживать достаточную пропускную способность журналирования.Для этого вам может потребоваться создать такую ​​структуру:

create table LogTable (
  LogTableID int identity(1,1),
  TableName varchar(100),
  Url varchar(200)
)

create table LogUser (
  LogUserID int indentity(1,1),
  UserName varchar(100)
)

create table LogField (
  LogFieldID int identity(1,1),
  FieldName varchar(100),
)

create table LogData (
  LogDataID bigint identity(1,1),
  LogDate datetime,
  LogTableID int references LogTable(LogTableID),
  LogFieldID int references LogField(LogFieldID),
  LogUserID int references LogUserID(LogUserID),
  Action char(1), -- U = update, I = insert, D = delete
  OldValue varchar(100),
  NewValue varchar(100)
)

Это должно быть достаточно быстро, чтобы быстро регистрировать данные, но при этом обеспечивать достаточную производительность для создания отчетов.Разработка индекса также важна, как правило, в порядке увеличения количества элементов, например, LogData (LogTableID, LingFieldID, LogDate).Вы также можете получить представление о секционировании, чтобы разрешить параллельные запросы.

...