質屋アプリケーション (任意の RDBMS):
各顧客 (マスター) が多くのトランザクション (詳細) を持つことができる 1 対多の関係。
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;
何人かの人々が、これは master を詳細に結合する正しい方法ではないと私に言いました。彼らは、私は常に customer.id[serial] を transactions.id[integer] に結合するべきだと言いました。
顧客が商品をポーンすると、店員は名前にワイルドカードを使用してマスターに問い合わせます。クエリは通常、複数の顧客を返します。事務員は適切な名前が見つかるまでスクロールし、'D' を入力して詳細トランザクション テーブルに変更します。すべてのトランザクションが自動的にクエリされ、次に事務員が 'A' を入力して新しいトランザクションを追加します。
transaction.id に結合する customer.id を使用する際の問題は、顧客テーブルがソートされた名前順に維持されているにもかかわらず、トランザクション テーブルを fk_id でクラスタ化すると、トランザクションが fk_id でグループ化されますが、それらは顧客名と同じ順序ではないことです。店員がマスターで顧客名をスクロールしているとき、システムは各顧客に属するクラスター化された取引を見つけるためにあちこちジャンプしなければなりません。新しい顧客が追加されるたびに、次の ID がその顧客に割り当てられますが、新しい顧客はアルファベット順に表示されません。id join を使って実験したところ、パフォーマンスの低下を確認しました。
名前結合と ID 結合を使用することの欠点は、顧客名を変更すると、トランザクションとの結合が切断されるため、名前の更新を許可しないことです。とにかく、どのくらいの頻度で顧客の名前を変更する必要がありますか? もう 1 つの欠点は、id が INT である name には 30 文字が必要であるため、.dat と .idx の方が大きくなることです。毎朝 sql proc が実行され、顧客とトランザクションがソートされた名前順にアンロードされ、テーブルが削除/再作成され、アンロードされたデータがロードされ、すべてのインデックスが再作成されてパフォーマンスが最適化されます。
トランザクションに名前列がない場合、名前結合の代わりに ID 結合を使用し、クラスター化されたトランザクションの順序を名前で保持するにはどうすればよいですか?
以下は、上記のスキーマで説明されているように、pk/fk 名を使用するときにデータが customer.dat および transactions.dat にどのように配置されるかの例です。
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 id を使用した同じデータです。
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
OK、ここで、1 ページの実行画面にはすべての顧客列とすべてのトランザクション列が含まれていることに注意してください。店員が顧客名でクエリを実行すると、その顧客に属する最初のトランザクション行が自動的に表示されるマスター/詳細指示があります。 . 次に、店員は「D」を押して取引をアクティブなテーブルにし、「A」を押して新しい取引を追加します。または、店員はすべての顧客取引をスクロールして特定の取引を更新するか、顧客に情報を提供するだけです。
pk/fk name メソッドを使用する場合、店員が顧客名をスクロールして目的の顧客を見つけると、応答は即座に行われます。一方、pk/fk id メソッドを使用する場合は、サポートされているインデックス作成を使用しても、応答時間が遅くなります。これは、店員が各顧客名をスクロールするときに、各顧客に属する対応するトランザクション グループを見つけるために、エンジンがトランザクション テーブル内のさまざまな場所にジャンプする必要があるためです。マスターで!
したがって、顧客のトランザクション行をグループ化し、顧客行と同じソート順にすることで、各顧客トランザクションの散在するグループ全体をジャンプする必要があるのではなく、インデックス作成でトランザクションをより迅速に見つけることができます。各顧客が自分の顧客 ID 番号を覚えていれば、私の問題は学術的なものになりますが、実際には、各顧客に顧客番号が記載された ID カードを渡しましたが、ほとんどの顧客がカードを紛失しました!
以下は、質屋が営業を開始する前に毎朝実行される毎日の reorg の例です。
{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;
時間があれば、誰にでもこれをテストするように挑戦します! .. 大きなテーブルがあると、より顕著になります。