Нормализация на базата данни: Използване на отделни таблици за съхраняване на едно поле

Понастоящем нашата база данни е настроена така, че платежните транзакции записват идентификатор на тип плащане и това се свързва с таблица с тип плащане (в брой, чек, кредит), която съдържа тези стойности. Пример:

Платежна транзакция:

  • ID
  • Количество
  • Дата
  • ID на вида на плащането

Начин на плащане:

  • ID
  • Тип плащане (в брой, кредит)

Въпросът ми е дали трябва просто да премахна или не таблицата с типа плащане и просто да запазя стойността на типа плащане като текст в платежната транзакция.

Това е подобно на този въпрос . с изключение на видовете плащане е доста сигурно, че никога няма да е необходимо да се добавят данни за всеки тип плащане. „Кеш“ не се свързва с нищо, няма нищо, което трябва да знам за самия Кеш, просто е.

Доколкото мога да преценя, предимствата и недостатъците на замяната на таблицата за тип плащане с едно поле биха били:

Плюсове

  • Премахва най-вече ненужното присъединяване, когато трябва да се намери тип плащане.
  • Типът плащане за дадена транзакция винаги ще отразява точно това, което е било към момента на записване на транзакцията. т.е. ако променя записа „В брой“ в таблицата с видовете плащания на „Кредит“ (по каквато и да е причина), всички платежни транзакции, които се свързват с Пари в брой, вече ще бъдат свързани с Кредит.

Против

  • Съхраняването на типа плащане като текстово поле ще забави сортирането по вид плащане и ще направи това сортиране малко по-объркано, отколкото е сега.
  • Типът плащане за дадена транзакция винаги ще отразява точно това, което е било към момента на записване на транзакцията. т.е. ако имах правописна грешка и типът плащане беше съхранен като „Кеш“, лесно бих могъл да поправя тази печатна грешка и всички транзакции, които се свързват с този тип плащане, автоматично ще бъдат актуализирани.

Склонен съм към премахване на таблицата с типове плащане и добавяне на едно поле към таблицата с платежни транзакции, какво препоръчвате да бъде най-добрият курс на действие?


person ACobbs    schedule 11.03.2012    source източник


Отговори (2)


Не съм съгласен с нито един от вашите про аргументи.

Премахва най-вече ненужното присъединяване, когато трябва да се намери тип плащане.

Има само вашето предположение, че това ще бъде тясно място в производителността. Денормализацията е нещо, което трябва да направите, когато имате данни, които казват, че трябва. Това не е едно от тези времена.

Типът плащане за дадена транзакция винаги ще отразява точно това, което е било към момента на записване на транзакцията. т.е. ако променя записа „В брой“ в таблицата с видовете плащания на „Кредит“ (по каквато и да е причина), всички платежни транзакции, които се свързват с Пари в брой, вече ще бъдат свързани с Кредит.

Не трябва да позволявате на някой да променя типа плащане по този начин. Промяната на типа плащане трябва да бъде друга транзакция със собствено времево клеймо.

Всяка релационна база данни може да обработва JOIN и нормализираните таблици. Вие сте виновни за преждевременната оптимизация, страхувам се.

Бих прекарал по-малко време в безпокойство за това и повече време в мислене как ще се справиш с историята. Колко време ще съхранявате транзакциите, преди да ги преместите в таблица с история? Мислили ли сте да разделите вашата база данни по месеци според времевия печат? Това би било по-достойно за вашите усилия.

person duffymo    schedule 11.03.2012
comment
Наистина говоря по-конкретно за предимствата, които те предлагат на програмиста/моето мързеливо аз. Знам, че JOIN ще има малко или никакво влияние върху производителността, но е много по-добре да напишете заявка без този JOIN, ако е възможно. Същото важи и за промяната на видовете плащане, потребителят няма възможност да го направи, но е доста обичайно да се налага да пренареждаме видовете плащания. Вместо да разчитате на различни идентификатори, мисля, че е много по-подходящо да разчитате на статичен „Кеш“ или „Кредит“, тъй като текстовата стойност никога няма да се промени много. - person ACobbs; 11.03.2012
comment
Никаква полза, която виждам. Не съм съгласен, че е по-хубаво. Бих се противопоставил, но това е вашата схема. - person duffymo; 11.03.2012
comment
Тогава мисля просто да оставя нещата така, както са. Наистина е болка да се променя половината от приложението всеки път, когато се промени вид плащане, но бих предпочел да съм в крак с най-добрите практики. Благодаря! - person ACobbs; 11.03.2012
comment
Както казах, бих препоръчал промяна на типа плащане като отделна транзакция със собствено времево клеймо. Както казахте, искате да запазите вида на плащането в деня, в който е направен оригиналът и когато е настъпила промяната. Не получавате това с АКТУАЛИЗАЦИЯ, освен ако нямате тригер за запис. - person duffymo; 11.03.2012

Ако премахнете таблицата PaymentType, заменяте проверка на външен ключ с ограничение CHECK на таблица:

PaymentType   CHAR(6) NOT NULL CHECK(PaymentType IN('Cash', 'Credit', 'Cheque')

Добре, пишете "чек" като "чек"; просто още една разлика между английски и американски.

Сега, това прави много по-трудно да се открие какви са възможните стойности; трябва да анализирате системния каталог, за да разберете. С отделната таблица можете да разгледате отделната таблица, за да разберете какво е позволено. Да предположим, че започнете да проследявате „Дебит“ отделно от „Кредит“; добавяте ред към таблица, срещу промяна на схемата на таблица. Да предположим, че решите, че трябва да запишете кои кодове са разрешени при бъдещи транзакции (така че „Кеш“ престава да бъде опция). Можете да добавите колона към таблицата тип плащане, за да посочите, че този код вече не е валиден; много по-трудно е да се направи това с просто ограничение CHECK.

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

Ако беше моят дизайн обаче, вероятно щях да използвам код CHAR(1) или CHAR(2) като идентификатор за типа плащане, а не цифрова колона. Разбира се, и трите типа започват с „C“, така че може би бихте използвали „A“ за пари в брой, „H“ за чек и „R“ за cRedit (и може би „D“ или „E“ за дебит или дебит) с код CHAR(1); с CHAR(2), ще използвате 'CA', 'CH', 'CR' (и може би 'DE'). Пълното име може да бъде съхранено в таблицата с видове плащания за използване в отчети. В този случай ползите не са огромни, но спестяването на 4 байта на запис върху достатъчно записи (достатъчно голям брой достатъчно малки записи) може да се превърне във фактор в разходите ви за съхранение. Разбира се, режийните индекси също влизат в действие; ако колоната в таблицата с платежни транзакции трябва да бъде индексирана, тогава по-малкото поле използва по-малко място за индексиране.

person Jonathan Leffler    schedule 11.03.2012