当铺应用程序(任何关系数据库):
一对多关系,其中每个客户(主)可以有多个事务(细节)。
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”改为“明细交易表”,自动查询所有交易,然后职员输入“a”添加新交易。
使用customer.id加入transaction.id的问题是,尽管customer表是按排序的名称顺序维护的,但是按fk_id组对事务表进行集群
按fk_id进行的交易,但它们与客户名称的顺序不同,因此当职员在主系统中滚动客户名称时,系统必须跨出整个位置来定位属于每个客户的集群交易。在添加每个新客户时,下一个id将分配给该客户,但新客户不会按字母顺序显示。我尝试使用id连接并确认性能下降。
使用name joins和id joins的缺点是,如果更改客户名称,则与他们的事务的join将被切断,因此我不允许更新名称。不管怎样,一个人多久需要更改一个客户的名字?另一个缩进是name需要30个字符,其中id是INT,所以.dat和.idx更大。每天早上执行一个sql proc,它按照排序后的名称顺序卸载客户和事务,删除/重新创建表,加载卸载的数据,并重新创建所有索引,从而保持性能优化。
如果事务没有name列,如何使用id联接而不是name联接,并且仍然按名称保留集群事务顺序?
以下是使用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
因此,当职员wilcard按客户主名称查询时,当职员滚动返回到当前列表中的名称时,客户交易将自动查询并快速显示,因为它们与主名称的排序顺序相同。
下面的示例是使用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
好的,现在请记住,我的perform 1-page屏幕包含所有customer列和所有transaction s列,并且有一个主/详细说明,当职员按customer name查询时,将自动显示属于该customer的第一个transaction行。然后,文员将按“D”使事务成为活动表,并按“A”添加新事务,或者文员可以滚动浏览所有客户事务以更新特定的事务,或者只向客户提供信息。
当使用pk/fk name方法时,当店员滚动客户名称以找到所需的客户时,立即响应。然而,当使用PK/FK 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;
如果你有时间的话,我会挑战任何人来测试这个!.. 当你有一张大桌子时,它更引人注目。
最佳答案
他们是对的。加入CHAR(30)文本字段(尤其是包含人名数据的字段)会很慢,效率很低,而且非常脆弱。人们确实会改变自己的名字(婚姻就是一个明显的例子),而且多个人可以有相同的名字。
您希望在表上创建适当的索引,以支持数据的显示顺序,而不要考虑集群。你的性能优化过程听起来像是在寻找一个地方发生的灾难。对不起,把桌子掉下来/摆成那样是自找麻烦。
我将从customer.id上的一个唯一索引、transaction.ticket_number上的一个唯一索引和transaction(id,ticket_number DESC)上的一个索引(用于性能而不是基数,因此强制执行唯一性并不十分重要)开始,并从中获取它。数据是按照在索引中出现的顺序从事务表返回的。
只有当所有其他查询优化途径都已用尽时,我才会考虑集群。
关于sql - customer.pk_name加入transaction.fk_name与customer.pk_id [串行]加入transaction.fk_id [整数],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3066714/