LINUX.ORG.RU

Разделение таблицы

 


0

1

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

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

Вопрос: стоит ли разделить таблицу на две - для активных и не активных? С одной стороны перенос из таблицы в таблицу это деградация индексов и лишнее время (перенос относительно редкий), с другой работа сервера идет только с активными клиентами и значит если и активные и не активные будут в одной таблице - работа будет линейно замедляться. Под работой понимается update (перерасчет данных) всех активных клиентов. Update редкий - несколько раз в сутки и относительно быстрый для отдельного клиента. Работа ведется с помощью очереди задач. В очередь помещаются диапазоны идентификаторов клиентов (сейчас это по 1000 клиентов в задаче), а воркеры выгребают данные клиентов из этих диапазонов и меняют данные. Соответственно если таблица будет одна то часто будут попадаться те клиенты для которых ничего делать не нужно, но выборка их данных уже будет сделана - соответсвенно время работы будет расти...

Что выбрали бы вы?

★★★★

Последнее исправление: quest (всего исправлений: 2)

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

mky ★★★★★
()
Ответ на: комментарий от mky

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

quest ★★★★
() автор топика

Одна таблица скорее всего будет заметно медленнее для выборки только активных/неактивных еще и из-за разреженности данных на диске, если с этим специально не бороться(CLUSTER).

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

disarmer ★★★
()
Ответ на: комментарий от quest

Сотни миллионов уже страшновато. Наверное, имеет смыл потестировать.

Если у вас неактивный клиент не может стать активным, то в случае двух таблиц, та, которая большая, получается ″insert-only″, по ней VACUUM не нужен. С другой стороны, если у вас 100 млн. возникло за пять лет, это в среднем 55 тыс. в сутки переходов пользователя из активного в неактивный (перестроений индекса).

mky ★★★★★
()
Ответ на: комментарий от disarmer

cluster,reindex,vacuum будем применять. Для выборки эти две таблицы сейчас могут выглядеть как одна через наследование.

quest ★★★★
() автор топика
Ответ на: комментарий от anonymous

для приложения будет одна таблица, по факту две.

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

quest ★★★★
() автор топика
Ответ на: комментарий от mky

Если у вас неактивный клиент не может стать активным

Может. Снова оплатит подписку и станет, но это редкая операция. Клиент зарегистрировался - я его добавляю в таблицу не активных. Может он там так и останется. Если оплатит подписку на три месяца - я его перенешу в таблицу активных. Прошло три месяца - процесс меняющий данные понимает это и переносит клиента в таблицу не активных. Переносы эти и наследования таблиц вроде и лишнее нагромаждение, зато время обработки активных пользователей не будет линейно расти из за замусоривания не активными.

quest ★★★★
() автор топика
Ответ на: комментарий от quest

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

anonymous
()
Ответ на: комментарий от anonymous

очень хорошая мысль! спасибо!

quest ★★★★
() автор топика

А как воркеры будут выгребать ровно по тысяче активных клиентов, ведь их id будут сильно разрежены и простыми диапазонами id этого не добиться.

anonymous
()
Ответ на: комментарий от anonymous

сначала берем начальный id в пакете равным нулю и примерно так получаем конечный id в пакете:

SELECT
        id
FROM
        (
            SELECT
                   id
            FROM
                   client
            WHERE
                   id >= ТУТ_НАЧАЛЬНЫЙ_ID
            ORDER BY id ASC
            LIMIT ТУТ_РАЗМЕР_ПАКЕТА
        ) AS client
ORDER BY id DESC
LIMIT 1;

потом берем начальный id равным конечный id + 1 и так пока ничего не прочитается

quest ★★★★
() автор топика
Последнее исправление: quest (всего исправлений: 1)
Ответ на: комментарий от quest

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

Если с ним будут проблемы, можно привязаться к размеру пула воркеров, и раскидывать клиентов по воркерам в момент добавления/удаления активного клиента.

anonymous
()
Ответ на: комментарий от anonymous

то-же хорошая мысль, спасибо!

quest ★★★★
() автор топика
Ответ на: комментарий от anonymous

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

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

anonymous
()
Ответ на: комментарий от anonymous

угу, потому что операция сделать клиента активным реже чем операция расчета данных для активных клиентов

quest ★★★★
() автор топика
Ответ на: комментарий от quest

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

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

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

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

anonymous
()
Ответ на: комментарий от anonymous

Можно держать таблицу: (номер_воркера, текущая_загруженность) и обновлять её при добавлении/удалении активного клиента. А каждого активного клиента нужно привязать к номеру его воркера.

anonymous
()
Ответ на: комментарий от anonymous

В смысле insert с join, я хотел сказать.

anonymous
()

работа будет линейно замедляться

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

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

Не забывайте, это сотня миллионов клиентов не продливших подписку😊 клиенты не продляют подписку, не платят, денег мало, модернизировать оборудование не на что! 😊

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.