nepster-web
@nepster-web

Стоит ли отходить от нормализации бд, чтобы улучшить производительность?

Смысл следующий, есть таблица payments - в которую записывается история денежного оборота.
Например:
- пользователь выводит средства: создается запись в таблице withdrawals и запись в payments
- пользователь переводит средства: создается запись в таблице transfers и запись в payments
- пользователь активирует аккаунт: создается запись в таблице activations и запись в payments

Тоесть любое изменение пользовательского счета фиксируется в payments, а так-же по необходимости в других таблицах.

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

Например:
30.09.2016, 15:00 Перевод средств Пользователю Вася

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

Теперь собственно задача показать например логин того, кому были переведены средства. Это уже есть в таблице transfers и необходимо еще продублировать в payments.

У меня есть 2 варианта.
1) завести entity_id и хранить идентификатор на запись из нужной таблицы, а зная type и system уже делать манипуляции.
- минус такого подхода в том, что если я вывожу 100 записей на экран, мне нужно постоянно их джоинить в некоторых случаях даже очень жирно джойнить.
- еще 1 минус в том, что так как entity_id будет связываться с разными таблицами, в нее невозможно поставить индекс, что не гарантирует целостность.

2) создать текстовое поле data и засовывать туда просто логин ну и другую необходимую информацию.
- минус такого подхода в том, что если пользователь поменяет логин (а такое конкретно у нас частое явление из-за перепродажи аккаунтов), то история уже будет показывать неверные данные.

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

Что вы можете мне посоветовать или подсказать в данном вопросе ?
  • Вопрос задан
  • 268 просмотров
Решения вопроса 2
usdglander
@usdglander Куратор тега PHP
Yipee-ki-yay
Не прочёл весь текст вопроса, но с уверенностью могу сказать "ДА"! Любая реальная разработка - это баланс между строгостью и производительностью. Во всех статьях по нормализации, говорится что можно всё таки денормализировать базу для повышения производительности.
Ответ написан
@dmitryKovalskiy
программист средней руки
Порой для создания отчетов действительно проводят денормализацию с целью повышения производительности. Но в вашем случае мне кажется нужно смотреть в другую сторону - к примеру подумать об индексах или может сами запросы не оптимальны.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
copist
@copist
Empower people to give
Можно завести ещё одну таблицу - список тех, кто поменял что-то совсем недавно и для него надо обновить вычисленное поле. Проходить только по ней. Сократит время обновления.

Или перевычислять это поле по факту изменений, но асинхронно, через очереди.
Ответ написан
@nApoBo3
Изложен все довольно сумбурно. Денормализация имеет смысл, только тогда, когда профит от выигрыша в производительности выборки покрывает пенальти от объема хранения, скорости выборки и скорости вставки, а так же пенальти на поддержку данной системы.
Если мы говорим от денормализации для целей вывода информации пользователю, то чаще всего такая операция не оправдана, проще выполнить данную операцию на стороне пользователя.
В вашем случае, насколько я понял, таблица payments являеться технической, ее наличие само по себе уже денормализация( вы отдельно храните дубли данных, которые можно получить из других источников ), следовательно она зачем-то нужна. Если она нужна для ускорения технических операций( например предварительный пересчет суммы счета ), то ввод в нее доп.полей которые не нужны для данных операций это ошибка. Если цель ее существования быстрый вывод пользователю суммарной и сжатой информации по операциям, то нам в ней нужна вся информация которую одновременно хочет видеть пользователь без выполнения под запросов к целевым таблицам.

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

Если создавать поле дата, то его можно сделать json или xml с произвольно структурой. Зачем его обновлять не очень понятно, это поле используется исключительно для ускорения вывода информации, и выводит информацию в таком виде в котором она была на момент операции.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы