关系表是否应包含重复数据以加快查询速度

时间:2013-01-14 13:21:06

标签: mysql database-design indexing database-performance

我有一个包含4个表的MySQL数据库:

job
job_application
client
candidate

每个表都有自己的主键,即job_idjob_application_idclient_idcandidate_id

client表中的雇主可以在job表中发布职位。 job表包含标识客户端的client_id字段

candidate表中的候选人可以申请工作,在job_application表中插入一行。 job_application表格包含job_id字段和candidate_id字段,用于标识作业是什么以及申请者是谁

我在为Employers编写查询以管理他们收到的作业应用程序时遇到了一些问题。作为一个例子,这里是我写的一个从job_application

中删除行的函数
public function deleteJobApplications($job_application_ids) {
    $this->db->query("DELETE ja.* FROM " . DB_PREFIX . "job_application ja LEFT JOIN " . DB_PREFIX . "job j ON (j.job_id = ja.job_id) WHERE ja.job_application_id IN ('" . implode("','", array_map('intval', $job_application_ids)) . "') AND j.client_id = '" . (int)$this->client->getClientId() . "'");
}

由于client_id仅在job表格中引用,因此每次我想要LEFT JOIN或{{job时,我需要UPDATE DELETE表1}}来自job_application

我是否应该向client_id表添加另一个job_application字段,基本上复制数据库中已有的数据,或者为LEFT JOIN和{{UPDATE继续DELETE 1}}?

2 个答案:

答案 0 :(得分:2)

您的问题不是您需要通过将“client_id”作为冗余列来反规范化“job_applications”。 (目前接受的答案在这方面实际上是不正确的。)你的问题是你没有正确地规范化。如果,则“client_id”列已经位于该表中,并且您的问题将永远不会出现。

让我们假装候选人姓名,客户名称和职位名称是全球唯一的。

看起来像这样的表将满足谓词名为“candidate_name”的人员适用于公司“client_name”的“job_name”。

job_applicatons
Person named <candidate_name> applies for <job_name> at company <client_name>.

client_name  job_name                candidate_name  
--
Microsoft    C++ programmer, Excel   Ed Wood 
Microsoft    C++ programmer, Excel   Dane Crute 
Microsoft    C++ programmer, Excel   Vim Winder
Microsoft    C++ programmer, Word    Wil Krug
Microsoft    C++ programmer, Word    Val Stein
Google       Python coder, search    Ed Wood
Google       Programmer, compilers   Ed Wood
Google       Programmer, compilers   Val Stein

三列,没有id号,没有空值,没有nonprime属性,所有键。这种关系在6NF。

很明显,您可以通过从前两列中选择不同的值来创建作业(或作业)的表格。外键引用很明显。

jobs
Company named <client_name> offers <job_name>.

client_name  job_name
--
Microsoft    C++ programmer, Excel
Microsoft    C++ programmer, Word
Google       Python coder, search
Google       Programmer, compilers

以类似的方式,您可以从一组公司的第一列中选​​择不同的值,并从一组申请人的最后一列中选择不同的值。同样,外键引用应该是显而易见的。

clients
Company named <client_name> is a client.

client_name
--
Microsoft
Google

candidates
Person named <candidate_name> is looking for a job.

candidate_name  
--
Ed Wood 
Dane Crute 
Vim Winder
Wil Krug
Val Stein

所有这些表都在6NF。

在正确执行此操作时,除了自然键之外,使用代理键扩充表格不会更改正常格式。让我们用您的代理ID号替换“job_applications”中的自然键。进行替换会导致您的表格看起来像这样。 (实际上,你也可以在其他表格中做同样的事情。)

job_applications
--
client_id
job_id
candidate_id
primary key (client_id, job_id, candidate_id)
other columns go here...

请注意,client_id已经在那里。如果没有其他列,您仍然至少在5NF。

答案 1 :(得分:0)

要回答你的问题,这取决于你的情况,特别是表的大小,如果它是值得的话。 此过程称为非规范化。 例如,你可以在这里获得信息: http://en.wikipedia.org/wiki/Denormalization