Заявление в ломбард (любая РСУБД):
Отношение один-ко-многим, где у каждого клиента (мастера) может быть много транзакций (подробно).
customer(
id serial,
pk_name char(30), {PATERNAL-NAME MATERNAL-NAME, FIRST-NAME MIDDLE-NAME-INITIAL}
[...]
);
unique index on id;
unique cluster index on pk_name;
transaction(
fk_name char(30),
tran_type char(1),
ticket_number serial,
[...]
);
dups cluster index on fk_name;
unique index on ticket_number;
Несколько человек сказали мне, что это неправильный способ добавить мастера к деталям. Они сказали, что я всегда должен присоединять customer.id [serial] к Transactions.id [integer].
Когда клиент закладывает товар, клерк запрашивает мастера, используя подстановочные знаки в имени. Запрос обычно возвращает нескольких клиентов, клерк прокручивает до тех пор, пока не найдет нужное имя, вводит «D», чтобы перейти в детальную таблицу транзакций, все транзакции автоматически запрашиваются, затем клерк вводит «А», чтобы добавить новую транзакцию.
Проблема с использованием customer.id для присоединения транзакции.id заключается в том, что, хотя таблица клиентов поддерживается в отсортированном порядке имен, кластеризация таблицы транзакций по группам fk_id
транзакции по fk_id, но они не в том же порядке, что и имя клиента, поэтому, когда клерк прокручивает имена клиентов в мастер-системе, система должна перепрыгнуть через место, чтобы найти кластерные транзакции, принадлежащие каждому клиенту. По мере добавления каждого нового клиента этому клиенту присваивается следующий идентификатор, но новые клиенты не отображаются в алфавитном порядке. Я экспериментировал с использованием id-соединений и подтвердил снижение производительности.
Недостатки использования объединений имен и объединений идентификаторов заключаются в том, что если вы меняете имя клиента, объединение с его транзакциями прерывается, поэтому я не разрешаю обновлять имя. В любом случае, как часто нужно менять имя клиента? Другой недостаток: name требует 30 символов, где id - INT, поэтому .dat и .idx больше. Каждое утро выполняется процедура sql, которая выгружает клиента и транзакции в отсортированном порядке имен, удаляет / заново создает таблицы, загружает выгруженные данные, и все индексы воссоздаются, что сохраняет производительность оптимизированной.
Как я могу использовать соединения идентификаторов вместо соединений имен и при этом сохранять порядок кластеризованных транзакций по имени, если транзакция не имеет столбца имени?
Ниже приведен пример расположения данных в customer.dat и Transactions.dat при использовании имени pk / fk, как описано в приведенной выше схеме:
customer.id customer.pk_name transaction.fk_name transaction.ticket_number
----------- ------------------------------ ------------------------------ -------------
2|ACEVEDO BERMUDEZ, FRANCISCO J. ACEVEDO BERMUDEZ, FRANCISCO J.|123456
ACEVEDO BERMUDEZ, FRANCISCO J.|123789
3|ANDUJAR RODRIGUEZ, WILFREDO C. ANDUJAR RODRIGUEZ, WILFREDO C.|101010
ANDUJAR RODRIGUEZ, WILFREDO C.|121212
1|CASTILLO DIAZ, FRANKLIN J. CASTILLO DIAZ, FRANKLIN J. |232323
CASTILLO DIAZ, FRANKLIN J. |343434
Таким образом, когда клерк запрашивает открытку по имени мастера клиента, транзакции клиентов автоматически запрашиваются и быстро отображаются, когда клерк прокручивает имена, возвращенные в текущий список, поскольку они находятся в том же порядке, что и мастер.
Теперь следующий пример - это те же данные с использованием идентификатора pk / fk:
customer.pk_id customer.name transactions.fk_id transactions.ticket_#
-------------- ------------------------------ ------------------ ---------------------
2|ACEVEDO BERMUDEZ, FRANCISCO J. 1|232323
1|343434
3|ANDUJAR RODRIGUEZ, WILFREDO C. 2|123456
2|123789
1|CASTILLO DIAZ, FRANKLIN J. 3|101010
3|121212
Хорошо, теперь имейте в виду, что мой экран выполнения на 1 странице включает все столбцы клиентов и все столбцы транзакций, и есть инструкция master / detail, которая, когда клерк запрашивает имя клиента, первая строка транзакции, принадлежащая этому клиенту. автоматически отображается. Затем клерк нажимает «D», чтобы сделать транзакции активной таблицей, и «A», чтобы добавить новую транзакцию, или клерк может прокручивать все транзакции клиентов, чтобы обновить одну из них, или просто предоставить клиенту информацию.
При использовании метода имени pk / fk, когда клерк прокручивает имена клиентов, чтобы найти нужного клиента, ответ мгновенный. Принимая во внимание, что при использовании метода идентификатора pk / fk время отклика отстает, даже с поддерживаемой индексацией, потому что движок должен перейти в разные места в таблице транзакций, чтобы найти соответствующую группу транзакций, принадлежащих каждому клиенту, поскольку клерк прокручивает имя каждого клиента в мастере!
Таким образом, кажется, что строки транзакций клиента сгруппированы вместе и в том же отсортированном порядке, что и строки клиентов, что позволяет индексации быстрее находить транзакции, в отличие от необходимости перемещаться по разрозненным группам транзакций каждого клиента.Если бы каждый клиент мог вспомнить своего клиента, то есть номер, тогда моя проблема была бы академической, но в реальном мире мы даже дали каждому клиенту i.d. карточка с номером клиента, но большинство из них потеряли свои карточки!
Вот пример ежедневной реорганизации, выполняемой каждое утро перед открытием ломбарда:
{ISQL-SE (customer and transactions table reorg - once-daily, before start of
business, procedure}
unload to "U:\UNL\CUSTOMERS.UNL"
select * from customer
order by customer.pk_name;
unload to "U:\UNL\TRAN_ACTIVES.UNL"
select * from transaction where transaction.status = "A"
order by transaction.fk_name, transaction.trx_date;
unload to "U:\UNL\TRAN_INACTIVES.UNL"
select * from transaction
where transaction.status != "A"
and transaction.trx_date >= (today - 365)
order by transaction.fk_name, transaction.trx_date desc;
unload to "U:\UNL\TRAN_HISTORIC.UNL"
select * from transaction
where transaction.status != "A"
and transaction.trx_date < (today - 365)
order by transaction.trx_date desc;
drop table customer;
drop table transaction;
create table customer
(
id serial,
pk_name char(30),
[...]
)
in "S:\PAWNSHOP.DBS\CUSTOMER";
create table transaction
(
fk_name char(30),
ticket_number serial,
tran_type char(1),
status char(1),
trx_date date,
[...]
)
in "S:\PAWNSHOP.DBS\TRANSACTION";
load from "U:\UNL\CUSTOMERS.UNL" insert into customer {>4800 nrows}
load from "U:\UNL\TRAN_ACTIVES.UNL" insert into transaction; {500:600 nrows avg.}
load from "U:\UNL\TRAN_INACTIVES.UNL" insert into transaction; {6500:7000 nrows avg.}
load from "U:\UNL\TRAN_HISTORIC.UNL" insert into dss:historic;{>500K nrows}
create unique cluster index cust_pk_name_idx on customer(pk_name);
create cluster index tran_cust_idx on transaction(fk_name);
{this groups each customers transactions together, actives in
oldest trx_date order first, then inactive transactions within the last year in most
recent trx_date order. inactives older than 1 year are loaded into historic
table in a separate database, on a separate hard disk. historic table
optimization is done on a weekly basis for DSS queries.}
create unique index tran_ticket_num_idx on transaction(ticket_num);
create index tran_trx_date_idx on transaction(trx_date);
create index tran_status_idx on transaction(status);
[...;]
[grant statements...;]
update statistics;
Если у вас есть время, я БУДУ НИКОМУ ЗАПРОСИТЬ ЭТО!! Это более заметно, когда у вас большой стол.