2012-08-26 43 views
0

此表包含用户的照片(缩略图和完整)。
大部分查询都会有一个“WHERE user_id =?”条件。两列作为主键或一列作为PK +索引?

CREATE TABLE photos (
    "photo_id" serial, -- serial is postgres' autoincrement 
    "user_id" integer not null, -- foreign key to users table 
    "filename_thumbnail_50" varchar not null, 
    "filename_thumbnail_75" varchar not null, -- 75px x 75px thumbnail 
    "filename_full" varchar not null, 
    PRIMARY KEY ("photo_id", "user_id") 
); 

什么是最好的设计和/或性能设计这个用例:
- 像上面例子中的两列主键?
- 一个主键(photo_id)和user_id上的索引?

+2

你拥有的两列主键并没有什么意义,恕我直言。不应该是'(photo_id)'或'(user_id,文件名)'? –

+0

对不起,我已更新我的示例,因此它有点复杂 – younes0

+1

对于表中的每一行,每个列值都应该依赖于“密钥,整个密钥,除了密钥外”。 “依赖于”表示“正确的值由......标识”。将“user_id”添加到串行列将打破第二部分;你的牌桌不会处于第二常态,并且会受到相关异常的影响。查看关于关系数据库规范化的任何书籍或文章。 – kgrittn

回答

4

主键应该遵循您的业务规则,没有别的。由于照片本身没有“真实”(即自然)主键,因此使用序列作为PK绝对有意义。

将主键扩展为user_id没有任何意义,也没有任何用途(因为无论如何photo_id都是唯一的,只会增加索引维护的开销)。而随着user_id是在索引的第二列这是不太可能会被用于上user_id(不是不可能,但可能性不大)

所以我会去坚持使用PK上photo_id和添加索引限制查询在user_id(无论如何索引外键列总是一个好主意)。

+0

感谢您的解释,我应该了解更多关于索引。 – younes0

+1

@ younes0:我可以强烈推荐这个网站:http://use-the-index-luke.com它非常适合解释索引的工作原理。 –

+0

会做!谢谢 – younes0

2

由于user_id是密钥中的第二列,因此写入的主键不可用于通过user_id进行搜索。

您的第二个选择是最好的 - 仅在photo_id上使用主键,因为这是记录的唯一标识符,并在user_id上为您的查询添加单独的索引。

0

如果你有一个没有增加的ID,我不认为你需要user_id作为主键。你为什么不使用user_id的密钥到你的用户表(我想你有)?

0

如果您有专门用于识别目的的列(在本例中为photo_id),则不需要有第二个关键列。

如果您的情况可能有多个记录具有相同的photo_id和不同的user_ids,那么我认为最好有一个中间表来创建多对多关系并保留单个主键。例如:

CREATE TABLE photos (
    "photo_id" serial, 
    -- other columns 
    PRIMARY KEY ("photo_id") 
); 

CREATE TABLE users (
    "user_id" serial, 
    -- other columns 
    PRIMARY KEY ("user_id") 
); 

CREATE TABLE photos_users (
    "photo_user_id" serial, 
    "photo_id" integer, -- not sure if this datatype is correct for postgres 
    "user_id" integer, -- not sure if this datatype is correct for postgres 
    PRIMARY KEY ("photo_user_id") 
); 

据我所知 - 需要一个第二个键列那里是有问题的表中没有特定ID列,如果只有1键用于可能有重复。这样的一个例子是下面:

CREATE TABLE Person (
    "FirstName" varchar NOT NULL, 
    "LastName" varchar NOT NULL, 
    "PostalCode" varchar NOT NULL, 
    PRIMARY KEY ("FirstName", "LastName", "PostalCode") 
); 

在上述情况下FirstName将不足以唯一具有作为主键,也不会FirstNameLastName,所以在这种情况下,至少3列将被使用。当然最好有一个IDPersonID列并将其用作主键。

就性能而言,主键不会产生太大的影响。担心索引。确保将在WHERE子句或JOINAGGREGATE中使用的任何列都有索引。

+0

谢谢,会上课 – younes0