使用'字符'作为主键并从另一个表

时间:2018-01-27 20:40:35

标签: sql database postgresql database-design

考虑以下postgres(版本9.4)数据库:

testbase=# select * from employee;
 id |               name               
----+----------------------------------
  1 | johnson, jack                   
  2 | jackson, john                   
(2 rows)

testbase=# select * from worklog;
 id |             activity             | employee |            time            
----+----------------------------------+----------+----------------------------
  1 | department alpha                 |        1 | 2018-01-27 20:32:16.512677
  2 | department beta                  |        1 | 2018-01-27 20:32:18.112356
  5 | break                            |        1 | 2018-01-27 20:32:22.255563
  3 | department gamma                 |        2 | 2018-01-27 20:32:20.073173
  4 | department gamma                 |        2 | 2018-01-27 20:32:21.05962
(5 rows)

列名称'在表格'员工'属于character(32)类型且唯一,列'员工'在' worklog'引用' id'来自表'员工'。列' id'是两个表中的主键。

我可以通过发出以下内容来查看某位员工的所有活动:

testbase=# select * from worklog where employee=(select id from employee where name='johnson, jack');
 id |             activity             | employee |            time            
----+----------------------------------+----------+----------------------------
  1 | department alpha                 |        1 | 2018-01-27 20:32:16.512677
  2 | department beta                  |        1 | 2018-01-27 20:32:18.112356
  5 | break                            |        1 | 2018-01-27 20:32:22.255563
(3 rows)

我宁愿将查询简化为

testbase=# select * from worklog where employee='johnson, jack';

为此,我会改变员工的身份。在' worklog'中输入character(32)并声明' name'作为表'员工'的主键。专栏'员工'在' worklog'当然,会引用' name'来自表'员工'。

我的问题:

' worklog'中的每一个新行需要额外的32个字节来代表'员工的名字。或者postgres内部只保留指向外部字段的指针而不重复每个新行的名称?

我想我的问题的答案在文档中的某个地方,但我找不到它。如果有人可以提供相应的链接,将会非常有帮助。

PS:我确实找到了this thread,但是没有链接到某些官方文档。行为也可能已经改变,因为该线程已经超过七年了。

1 个答案:

答案 0 :(得分:2)

Postgres将存储您告诉它存储的数据。有些新的数据库会在引擎盖下进行压缩 - 而且Postgres可能具有启用它的功能(我不知道Postgres的所有功能)。

但是,你不应该这样做。由于三个原因,整数主键比字符串更有效:

  • 它们是固定长度的字节数。
  • 它们更短。
  • 整理不是问题。

坚持使用原始查询,但使用join

进行编写
select wl.*
from worklog wl join
     employee e
     on wl.employee = e.id
where e.name = 'johnson, jack';

我建议这样做,因为这与SQL的工作方式更加一致,并且更容易选择多名员工。

如果您想查看姓名而不是ID,请创建一个视图(例如v_worklog)并添加员工姓名。