sql - customer.pk_name加入transaction.fk_name与customer.pk_id [串行]加入transaction.fk_id [整数]

标签 sql mysql sql-server oracle clustered-index

当铺应用程序(任何关系数据库):
一对多关系,其中每个客户(主)可以有多个事务(细节)。

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/

相关文章:

php - 使用 ZEROFILL 精确比较两个数字

.net - SQL Server 中的列级压缩

sql-server - 在存储过程中使用 SAVE TRANSACTION SavePointName

sql - 为多于一列选择最大值?

mysql - AI ID 字段上的 WHERE 子句出现意外结果

sql - 有时创建数据库,但有时不创建

mysql - Group by Mysql 查询问题

Python,当我输入变量的实际值时,MySQL 语句有效,但在使用变量时却无效?

sql-server - 关闭/终止交易

java - 有条件地在 jooq 准备好的语句中包含子句