在新建表和数据仓库时,往往需要做出许多决定。一些在当时看起来似乎是无关紧要的决定,却终会导致你和你的客户在使用数据库的整个过程中饱尝痛苦。
  我们已经和数千人以及他们的数据库打过交道了,在经历了无数个小时的读写查询之后,可以说我们几乎见过所有的情况了。下面是我们总结出的有助于创建无痛模式(Schema)的10条规则。
  1. 只使用小写字母,数字和下划线
  不要在数据库、模式、表格或者列名上使用点、空格或者破折号。因为点号是用来识别对象的,通常只在 database.schema.table.column 这种情况下使用。
  在对象的名字中也包含点号会带来困扰。同样地,在对象名中使用空格将迫使你给查询加入一堆不必要的引号:
  select "user name" from events
  -- vs
  select user_name from events
  另外,一旦在表格或者列名上使用了大写字母,查询会变得更加难写。因为如果全部都是小写字母的话,人们没有必要去特别记忆用户表到底是Users还是users。
  不仅如此,当你终变更数据库或者将表复制到数据仓库中时,除了一些数据库以外,你无须记住哪个数据库是大小写敏感的。
  2. 使用简单且具有描述性的列名
  如果users表需要定义一个引用了packages表的外键,那么将其命名为package_id是个不错的选择。我们应该避免像是pkg_fk这样的又短又含糊的列名,因为其他人很难知道那是什么意思。具有描述性的名字能够使得其他人更容易理解模式,而且当团队扩大时这一点对于保持工作效率也是很重要的。
  不要使用模棱两可的名字命名可能有多种解释方法的数据。如果你发现自己正在以item_type或item_value这样的命名风格创建列时,那么可能说明你应该使用更多的带有具体名字的列了,像是photo_count、view_count和transaction_price。
  因为这样做的话,列中存储了什么样的数据总是可以由模式得知的,而并不需要由行中的其他值推导出来。
  select sum(item_value) as photo_countfrom itemswhere item_type = 'Photo Count'
  -- vs
  select sum(photo_count) from items
  不要使用表名作为列名的前缀。因为一般来说在users表中定义诸如user_birthday、user_created_at或者user_name这样的列名起不到什么辅助作用。
  后,还要避免将诸如column、tag或user这样的保留关键字用作列名。因为一旦使用了保留关键字,意味着不得不在查询语句中使用额外的引用符,而当有人忘记这么做的时候,数据库会产生非常令人困惑的错误信息。而且如果在本该是列名出现地方使用了关键字,那么数据库无法理解查询语句。
  3.使用简单且具有描述性的表名
  如果表名是由多个单词组成的,那么请使用下划线分割它们。因为package_deliveries要比packagedeliveries更容易读。
  如果可能的话,总是使用一个单词而不是两个,因为deliveries要更加容易阅读。
  select * from packagedeliveries
  -- vs
  select * from deliveries
  不要用模式的名字作为表名的前缀。如果你需要将一些表划入一个范围,那么只需将这些表放入到一个模式中即可。和有前缀的列名一样,诸如store_items、store_transactions或者store_coupons这样的表名,通常都是不需要额外的前缀的。
  我们推荐使用复数形式的名字为表命名(例如packages),并且对联合表的表名中的两个单词也都使用复数形式。单数形式的表名更可能意外地与关键字冲突并且一般在查询中其可读性也不高。
  4. 将整形作为主键
  无论你是正在使用各种UUID(通用识别码)类型的列作为主键,还是你认为加入带有自增长整型序列的主键根本没有意义(比如对于联合表),我们都建议你添加一个带有自增长整型序列的标准id列。这种类型的主键会使得特定的分析变得更加容易,比如从一组数据中只选出第一行。
  并且当导入数据的工作导致了数据的重复时,主键也会成为灵丹妙药,因为我们可以通过主键轻松删除特定的行:
  delete from my_table
  where id in (select ...) as duplicated_ids
  避免多列主键。当努力编写高效的查询时,多列主键将会导致查询语句很难理解,并且很难修改。我们可以使用一个整型的主键,或者一个多列的约束,再或者一些单列的索引来取代多列主键。
  5. 与外键一致
  命名主键和外键有许多种风格。我们建议诸位使用的是为普遍的风格,即对于任意的表格foo,将foo中的主键命名为id,将所有的外键命名为foo_id。
  另一种风格是使用全局统一的主键名。在这种风格下,表foo的主键称为foo_id,而所有的外键也称为foo_id。不过无论使用哪种风格,使用缩写的话(比如将users表缩写为uid),总是会造成困扰或名称冲突,所以应该避免使用缩写。
  而且,无论你选用了什么风格,都要坚持下去。不要在某些地方使用uid,而又在其他地方使用user_id或者users_fk。
  select _from packages join users on users.user_id = packages.uid
  -- vs
  select _from packages join users on users.id = packages.user_id
  -- or
  select *from packages join users using (user_id)
  除此之外还要留意外键并不显式匹配一张表的情况。一个名为owner_id的列可能是users表的一个外键,当然也可能不是。因此如果有必要的话,请将作为外键的列命名为user_id或者owner_user_id。