Реляционные БД: пригодны ли для такого?

Marinavo_0507

Есть простейшая схема подсчёта трафика.
Данные о трафике закладываются примерно в такую таблицу:

CREATE TABLE `ip_traffic` (
`id` bigint(20) NOT NULL,
`client` int(11) default NULL,
`class` smallint(6) default NULL,
`bytes` bigint(20) default NULL,
`time` bigint(20) default NULL,
PRIMARY KEY (`id`
KEY `i_time` (`time`,`client`
KEY `i_class` (`class`,`time`
KEY `i_client_time` (`client`,`time`
KEY `i_cct` (`client`,`class`,`time`)
)
Оно есть, и в целом неплохо работает.
Для каждого типичного вида запросов создано по индексу.
За несколько месяцев накапливается несколько гигабайт данных - в несколько раз больше объёма оперативной памяти на сервере.
Если пытаться складывать в таблицу более детальную информацию, данных будет ещё больше.
Проблема в том, что запросы, которым нужно перелопатить ну скажем несколько сот тысяч строк,
выполняются медленно.
Например, отчёт по месяцам, по трафику конкретного клиента - нужно, используя ключ `i_client_time`,
выбрать данные (их относительно немного, скажем около 1/1000 от всех строк и их немного обработать.
Но это делается несколько минут.
Как я понимаю, это происходит потому, что нужные строки разбросаны по всей таблице,
и нужно много операций чтения с диска, с позиционированием головки для каждой.
Используется MySQL.
Вопрос: может ли переход на другую реляционную БД сильно улучшить ситуацию,
если да, то как примерно эта другая СУБД добьётся увеличения скорости:
нужно ведь хранить данные так, чтобы для каждого индекса строчки хранились примерно в нужном порядке,
IMHO без дублирования тут не обойтись?

Marikun

Вопрос: может ли переход на другую реляционную БД сильно улучшить ситуацию,
если да, то как примерно эта другая СУБД добьётся увеличения скорости:
В первую очередь поможет перепроектирование схемы данных. (Я не о приведенной табличке, с ней почти все в порядке, а в целом о базе). Я так понимаю, что тут речь идет о системе OLTP. В случае необходимости построения аналитических запросов, необходимо уже строить хранилище данных (OLAP). Естественно, есть специализированные реляционные СУБД заточенные для таких задач. Например, Terradata, Red Brick, Informix XPS, IBM DB2 Warehouse edition.

gopnik1994

MySQL, афаик, показывает одну из лучших производительностей на больших базах.
Переход на что-то более продвинутое (типа FB, Oracle) только уменьшит производительность.
Переход на что-нибудь подобное по классу MySQL большого выигрыша в производительности все равно не даст.
Имхо, лучший выход - данные более 2-3-х месячной давности тупо сносить в архив, закатывать на болванку и забрасывать в далекий ящик. Можно при этом перед удалением старой детальной инфы какую-то более статистически укрупненную инфу (много меньшую детальной которая может пригодится для сбора отчетов и пр., сохранять в другой табличке.

Marikun

MySQL, афаик, показывает одну из лучших производительностей на больших базах.
Большие это сколько?

gopnik1994

афаик, разработчики уверяют что обладают базой около террабайта...

Marikun

Ну это явно не самая большая база в мире %). Кроме того, любая промышленная СУБД терабайт выдерживает легко, даже MS SQL (при условии, что с блокироваками напряги не возникнут %)

Marinavo_0507

> В случае необходимости построения аналитических запросов, необходимо уже строить хранилище данных (OLAP).
Фактически, отдельная база для таких запросов?
Тогда будет проще отказаться от реляционных баз и сделать что-то специализированное,
благо все типы запросов, которые нужно выполнять быстро, известны заранее.

stm7884696

а че это за хранилище такое OLAP вообще?
Где можно это поботать ?

gopnik1994

я и не говорю, что эта самая большая
просто для определения порядка "большая".

ava3443

> Тогда будет проще отказаться от реляционных баз и сделать что-то специализированное
Ну супер. Ещё велосипед изобретать... Ты твёрдо уверен, что тебе первому в мире пришло в голову решить эту задачу?

gopnik1994

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

Marinavo_0507

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

Hastya

Плохо знаю MySQL, а с точки зрения Оракла средств оптимизации немного: индексы, partitions, возможно materialized views...
У нас в свое время руками делали процедуру "свертки" больших "исторических" таблиц в маленькие. Это, в частности, приводит к денормализации схемы.

Marikun

Фактически, отдельная база для таких запросов?
Тогда будет проще отказаться от реляционных баз и сделать что-то специализированное,
благо все типы запросов, которые нужно выполнять быстро, известны заранее.
Да, у любого крупного предприятия, уже даже в России, для аналитических запросов используется отдельаная база. И действительно, далеко не всегда это реляционка. Очень часто используются многомерные СУБД. Но они не позволяют получать детальную инфомрацию и объем анализируем информации ограничивается где-то цифрой в 70-80 гб, дальше они не справляются. В таких случаях нужна реляционка, либо комбинация и той и другой.
Насчет того, что запросы известны заранее, то в таком случае проще всего написать sql-запросы по существующей OLTP и воспользоваться какм-то механизмом для кэширования ответов, то есть чтобы такие запросы выполнялись реально ночью, а пользователи получали готовый результат. Проблема в том, что такие статичные отчеты подходят не часто, в большинстве случаев пользвователи хотят иметь возможность построения отчетов на лету (ad-hoc). То есть не идти каждый раз к программистам и ждать отчета неделю, а строить нужные отчеты мышкой, и не зная sql.

TYU_2008

Многие делают. Мне тут недавно рассказывали, что биллинг то ли Билайна, то ли Мегафона использует специализированную базу.

Marinavo_0507

Агрегирование сделать легко, даже в реальном времени если понадобится. Тогда таблицы станут маленькими.
Я собственно так и собираюсь сделать.

Marikun

а че это за хранилище такое OLAP вообще?
OLAP -online analytical processing
Хранилище данных в большинстве случаев синоним термину OLAP.
Где можно это поботать
Довольно-таки неплохая начальная информация в статьях на Olap.ru.
Самая лучшая инфа - книжки Ralph'a Kimball'a, на русском их к сожалению нет

Marikun

Многие делают. Мне тут недавно рассказывали, что биллинг то ли Билайна, то ли Мегафона использует специализированную базу.
И там и там да и в МТС тоже билинг на Оракле.
Скорее для решения каких-то подзадач (может, и связанных с билингом, используется что-то специализированное)

Ivan826

Мегафон сидит на постгресе

TYU_2008

Мне рассказывали что там (где именно я забыл) бакенд на Оракле, а все рассчеты ведутся в специализированной базе.

TYU_2008

не верю

Marikun

Мегафон сидит на постгресе
Как следующий раз буду с ихними айтишниками общаться обязательно спрошу есть ли у них что-нить на постгрессе. Очень сомневаюсь, ибо у постгресса, по моему опыту общения с ним, очень большие траблы с блокировками.
В мегафоне оракл, насколько я знаю, корпоративный стандарт. Даже в плане application server'ов, несмотря на то, что у Оракла они убогие.

otvertka07

в одной небезызвестной ERP системе для этого используют 2 таблицы: LedgerTrans, где лежат все проводки и LedgerBalancesTrans, в которой лежат суммы проводок по периодам (периоды настраиваются отдельно, обычно это месяцы и годы). Часть суммы считается по закрытым периодам, остальное досчитывается по LedgerTrans, работает быстро :-)

sergey_m

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

SvinkaVJeansah

Все решается только перепроектированием базы. Результаты сложных запрсов (тех же месячных т.е. "отчеты" можно загонять в другие таблицы, например, а не генерить постоянно. А смена реляционной бд мало на что повлияет: та же беспорядочность в хранении строк - по сути заложена в спецификации sql.

daru

А смена реляционной бд мало на что повлияет: та же беспорядочность в хранении строк - по сути заложена в спецификации sql.
Вот это не совсем верно.
Год назад мне довелось позаниматься этой же проблемой. Правда там были бухгалтерские проводки. Результат был такой (в случае нашей конкретной системы что аналитические запросы mssql выполнял намного быстрее, чем mysql. Причем с ростом размера БД разрыв увеличивался. Если кому интересно, могу поподробнее рассказать, а то скажут, что обсираю mysql.
А насчёт "беспорядочности в хранении строк" она может и "заложена в спецификации sql", но кроме спецификации есть еще и реализация. А тут уже имеется поле для деятельности. Например можно (если СУБД поддерживает) создать materialized views (вспомогательную таблицу на крайняк в которых сделать кластерные индексы по тем полям, по которым будет происходить группировка. Иногда это может сильно сократить время построения аналитического отчета за счёт увеличения времени добавления одной записи в БД.

voronetskaya

тут точно все правильно написано?:
сократить время построения аналитического отчета за счёт увеличения времени

ava3443

2 : Чем больше индексов, тем больше времени тратится на добавление одной записи. Разве не так?

daru

"В Советском Союзе секса нет" <c> (цитирую по памяти, а она мне бывает изменяет...) или чё?

teonazoi

Так но не линейно. Если включаешь индексы добавление/удаление записи вызывает еще и изменение в индексах, но если они на базе Б деревьев, то от количества индексов(размера базы) скорость почти не изменяется.

ava3443

Ну я про линейность ничего и не говорил

bastii

По идее должна быть линейная зависимость от числа индексов.

voronetskaya

ну да, я ступил, ну бывает в 4 утра

daru

нп

SvinkaVJeansah

А насчёт "беспорядочности в хранении строк" она может и "заложена в спецификации sql", но кроме спецификации есть еще и реализация.
SQL не гарантирует хранение строк в каком-либо определенном порядке, посему завязывать на какие-то тонкости конкретной реализации более-менее серьезный проект не стоит.проект

SvinkaVJeansah

Есть простейшая схема подсчёта трафика.
Данные о трафике закладываются примерно в такую таблицу:
code:
CREATE TABLE `ip_traffic` (
`id` bigint(20) NOT NULL,
`client` int(11) default NULL,
`class` smallint(6) default NULL,
`bytes` bigint(20) default NULL,
`time` bigint(20) default NULL,
PRIMARY KEY (`id`
KEY `i_time` (`time`,`client`
KEY `i_class` (`class`,`time`
KEY `i_client_time` (`client`,`time`
KEY `i_cct` (`client`,`class`,`time`)
)
Оно есть, и в целом неплохо работает.
Для каждого типичного вида запросов создано по индексу.
За несколько месяцев накапливается несколько гигабайт данных - в несколько раз больше объёма оперативной памяти на сервере.
Если пытаться складывать в таблицу более детальную информацию, данных будет ещё больше.
Проблема в том, что запросы, которым нужно перелопатить ну скажем несколько сот тысяч строк,
выполняются медленно.
Например, отчёт по месяцам, по трафику конкретного клиента - нужно, используя ключ `i_client_time`,
выбрать данные (их относительно немного, скажем около 1/1000 от всех строк и их немного обработать.
Но это делается несколько минут.
Как я понимаю, это происходит потому, что нужные строки разбросаны по всей таблице,
и нужно много операций чтения с диска, с позиционированием головки для каждой.
Используется MySQL.
Вопрос: может ли переход на другую реляционную БД сильно улучшить ситуацию,
если да, то как примерно эта другая СУБД добьётся увеличения скорости:
нужно ведь хранить данные так, чтобы для каждого индекса строчки хранились примерно в нужном порядке,
IMHO без дублирования тут не обойтись?
Вообще, чтобы что-то понять, стоит указать запросы, которые ты в эту базу посылаешь. Также уточнить, что представляют из себя time и bytes. У меня на мускле трафик ложится вот в такую простую базу:
 mysql> describe raw;
+--------+------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------+------+-----+-------------------+-------+
| id | bigint(20) | | PRI | 0 | |
| data | bigint(20) | | | 0 | |
| stamp | timestamp | YES | PRI | CURRENT_TIMESTAMP | |
| reload | bigint(20) | YES | | NULL | |
+--------+------------+------+-----+-------------------+-------+
4 rows in set (0.02 sec)

mysql> describe counters;
+-----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+----------------+
| id | bigint(20) | | PRI | NULL | auto_increment |
| name | char(255) | YES | | NULL | |
| alias | char(255) | YES | | NULL | |
| rule | int(11) | | | 0 | |
| rule_body | char(255) | | | | |
| dir | enum('in','out') | | | in | |
+-----------+------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
Таблица counters - что и откуда снимать, raw - данные. Колонка raw.data - показания счетчика файерволла на момент времени raw.stamp, а raw.reload - индикатор сброса счетчика.
Соответственно в моей конфигурации все запросы по сумме траффика за период выполняются быстро и просто.
Хотим узнать траффик id x за период с t1 по t2.
Идеал: reload(t1, x) = reload(t2, x) (т.е. счетчик не перегружался) считается банальной разницей raw.data(t2, x) - raw.data(t1, x наличие перезагрузок тоже не сильно влияет на сложность запроса и его производительность.

SvinkaVJeansah

Да, забыл добавить - моя база на 10 счетчиках растет на 3Мб в месяц при снятии показаний раз в 20 мин.

daru

SQL не гарантирует хранение строк в каком-либо определенном порядке, посему завязывать на какие-то тонкости конкретной реализации более-менее серьезный проект не стоит.проект
В данном случае это не тонкости, а заявленная фича программного продукта (clustered index). Иногда trade off при решении какой-то задачи смещен в пользу производительности, а не концепции. В этом случае вполне позволительно использовать и не такие особенности реализации...
И еще. Например биллинговая система, используемая компанией-сотовым оператором - это серьезный проект? imho серьезный. При этом заранее известно, что слезть с оракла на любую другую БД будет стоить этой компании, например, > 100 млн $. Стоит ли в такой ситуации завязываться на "какие-то тонкости конкретной реализации"? Вполне! Только нужно четко представлять, где проходит граница, чего еще можно, а чего уже нет. Ну это уже опыт и здавый смысл решают...

SvinkaVJeansah

Согласен. )

Marinavo_0507

Запрос выглядит так

SELECT FROM_UNIXTIME(time, '%Y/%m') as Month, class, sum(bytes) as B
FROM ip_traffic
WHERE client=$client AND time>=UNIX_TIMESTAMP($start_time)
GROUP BY Month, class

SvinkaVJeansah

Вижу как минимум два варианта улучшения производительности:
1) хранение заранее просчитаных выборок в отдельной таблице вида
------
id,
client,
class,
sum_bytes,
time,
enum type ("day", "month", "year")
------
2) Хранение в твоей таблице интегральных значений счетчиков вместо интервальных, тогда любой траффик за период - это разница двух значений, полученных двумя простыми запросами, которые будут выполняться быстрее, чем sum из-за которого и возникают тормоза.
Оставить комментарий
Имя или ник:
Комментарий: