在新建表和数据仓库时,往往需要做出许多决定。一些在当时看起来似乎是无关紧要的决定,却最终会导致你和你的客户在使用数据库的整个过程中饱尝痛苦。
我们已经和数千人以及他们的数据库打过交道了,在经历了无数个小时的读写查询之后,可以说我们几乎见过所有的情况了。下面是我们总结出的有助于创建无痛模式(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_count
from items
where 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列。这种类型的主键会使得特定的分析变得更加容易,比如从一组数据中只选出第一行。
并且当导入数据的工作导致了数据的重复时,主键也会成为灵丹妙药,因为我们可以通过主键轻松删除特定的行:
deletefrom my_table
whereidin(select...)as duplicated_ids