2013-06-10 2 views
0

У меня есть требование разработать систему. Часть системы состоит в том, что каждый день рассчитывается плата за человека (человеку присваивается $ x.xx в день на основе некоторых правил) и сохраняется в таблице транзакций, которая в настоящий момент состоит из personId, сумма и дата.Настольная конструкция для эффективности

CREATE TABLE DailyTransaction 
(
    DailyTransaction INT NOT NULL IDENTITY(1,1) PRIMARY KEY, 
    PersonId INT NOT NULL, 
    TransactionDate DATE NOT NULL 
) 

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

Думаю, хранение даты, повторение слишком много. И могут быть запросы на эту дату позже. Итак, я бы хотел создать таблицу «DailyRun», которая содержит дату, а также идентификатор (и больше столбцов позже, если необходимо). Итак, когда я делаю ежедневную платежную вставку для заполнения 8000 строк, я сначала создаю запись DailyRun с датой, а затем присваиваю этот идентификатор для этой строки таблице транзакций.

CREATE TABLE DailyRun 
(
    DailyRunId INT NOT NULL IDENTITY(1,1) PRIMARY KEY, 
    RunDate DATE NOT NULL 
) 

CREATE TABLE DailyTransaction 
(
    DailyTransaction INT NOT NULL IDENTITY(1,1) PRIMARY KEY, 
    PersonId INT NOT NULL, 
    DailyRunId INT NOT NULL 
) 

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

Это кажется хорошо до сих пор (если кто-то не видит проблему?)

НО, теперь вопрос.

Другое требование заключается в том, что в течение дня в таблицу транзакций можно добавить специальный платеж. Итак, дополнительный разовый платеж. Но он не создается как Run. Таким образом, ни одна строка в таблице DailyRun. Идея - это унифицированный идентификатор DailyRun в таблице Transaction, но ... когда мне нужно получить все транзакции на определенную дату - ну, нет поля даты ... и теперь RunID установлен .. так что это не будет найденный.

Что я могу сделать, это разрешить Null RunID, а также поле с нулевым значением «AdHocPaymentDate». Итак, если это Adhoc-платеж, я могу оставить RunID null и заполнить AdHocPaymentDate?

И если это запланированный платеж, я заполняю RunID и оставляю AdHocPaymentDate равным нулю?

Но, не являются ли поля, допустимые для нитевидности, медленными или не рекомендуется по какой-либо причине?

Есть ли лучший способ справиться с этим? Может быть, отдельная таблица «Ad Hock Payment», которая содержит специальные платежи, в дополнение к таблице, которая содержит регулярные ежедневные платежи?

+6

«Я думаю, что хранение даты повторяется слишком много» - это, наверное, плохое предположение. Для «даты» требуется 3 байта для хранения («datetime» требует 8, 'datetime2' между 6 и 8 байтами) - по сравнению с накладными расходами на создание новой таблицы, эффективно индексируя ее и помещая FK на место? И, как и в случае с любым вопросом производительности, единственный способ узнать это - попробовать все * свои * данные в * вашей * среде. Слишком редко работает удаленная настройка производительности с помощью хаков и чувств. –

+0

Спасибо Damien. Дополнительная таблица также может содержать дополнительные данные, которые я бы нашел полезными, например, обработанный флаг состояния (был ли этот запуск обработан и отправлен платеж по форме?). Но я согласен - если у него просто дата - это может быть не полезно. – Craig

+1

Даже если вам нужно будет хранить много дополнительной информации в таблице DailyRun позже, то для эффективности запросов я бы дублировал TransactionDate в таблице DailyTransaction (используя ваш первый проект). В наших устаревших структурах данных есть несколько таблиц (строк документов), глобальная PITA запрашивает строки и заголовок ссылки только для получения даты оттуда. – Arvo

ответ

1

Кажется, что существует потребность в бизнесе, чтобы отличать специальные платежи от ежедневных прогонов. Думаю, вы могли бы работать с таким решением. Использование «DailyRun» и «AdHoc» как типы транзакций, а затем делает бизнес-аналитики вставить транзакцию правильно от ежедневных пробегов (услуг) и adhocs (взаимодействие с пользователем)

CREATE TABLE [TransactionType] 
(
    [Id] INT NOT NULL IDENTITY(1,1) PRIMARY KEY, 
    [Name] NVARCHAR(40) 
) 

CREATE TABLE [Transaction] 
(
    [Id] INT NOT NULL IDENTITY(1,1) PRIMARY KEY, 
    [TransactionTypeId] INT NOT NULL REFERENCES TransationType 
    [PersonId] INT NOT NULL REFERENCES person 
    [Date] DATE NOT NULL 
) 
1

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

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


Как я начну. , ,

По вашему описанию это не таблица транзакций. Это таблица платежей.

create table payments (
    payment_id integer not null, 
    payment_date date not null, 
    payment_amount decimal(12, 2) not null 
    check (payment_amount > 0), 
    -- For identifying a(d hoc) and r(un) payments 
    payment_type char(1) not null 
    check (payment_type in ('a', 'r')), 
    person_id integer not null, -- references a table not shown 
    primary key (payment_id), 
    unique (payment_id, payment_type), 
    unique (payment_date, payment_type, person_id) 
); 

Важное значение имеет уникальное ограничение на {payment_date, payment_type, person_id}. Ваше описание, по-видимому, требует не более одного «прогона» платежа за день на одного человека и не более одного специального платежа за дату на человека. В любом случае вам нужно уникальное ограничение на реальные данные в дополнение к ограничению первичного ключа для суррогатного идентификационного номера.

Важное значение имеет также уникальное ограничение на {payment_id, payment_type}. Если вам нужно сохранить более подробную информацию о просроченных платежах или о специальных платежах, вы можете создать таблицу, подобную этой.

create table payments_ad_hoc (
    payment_id integer not null, 
    payment_type char(1) not null 
    default 'a' 
    check (payment_type = 'a'), 
    other_columns_go_here char(1) not null 
    default 'x', 
    primary key (payment_id), 
    foreign key (payment_id, payment_type) 
    references payments (payment_id, payment_type) 
); 

Сочетание проверочного ограничения и ограничение ключевого иностранного гарантирует, что строки в этой таблице будут ссылаться на специальную компенсации, а не только любой платеж. Структура для «прогона» платежей будет аналогичной.