使用主键值字符“1”而不是int值1

时间:2013-01-07 03:05:36

标签: database architecture

嗯,我对数据库架构知之甚少,但我真的不明白CTO的想法,但他坚持用字符作为 我们使用的所有表的主键的列类型。 但主键仍然如下所示 - > 1,2,3 ...等等。它们是数字的。 所以我使用integer + auto_increment进行合成PK

但CTO表示,他不能在PK上使用LIKE条件发出查询,这很糟糕?!

  1. 特别是当您的PK是数字时,是否可以使用PK字符?
  2. 在PK上使用类似条件是否正确?
  3. PS - 所以不是自动递增/触发,序列CTO发出选择查询提取 表中最大的值,他加1,然后他将该值转换为字符串 然后存储它。

    编辑
    谢谢您的帮助 !但我需要说服他,这将是一场灾难。 我只是被告知这个(在这种情况下的角色4 PK)是一个坏主意。 他的论点是...... 1.角色PK不会占用太多空间。
    2.如果使用int类型PK,数据库查询优化器必须重新读取您的查询 因为你必须发出类似的东西 "select * from employee where name like 'somename'

    Select * from employee where id = 6
     因为where子句改变了。
    他强烈主张我们使用的东西就像是 "select * from employee where @columnName like @value"
    他这样说,查询优化器会运行得更好。

    我如何证明或给他一些改变主意的正当理由?

    谢谢:)

3 个答案:

答案 0 :(得分:4)

你的首席技术官犯这个决定错误的原因很多;我先谈谈几点:

  1. 正如您所指出的,您必须采取额外步骤来生成新的自动递增PRIMARY KEY。这是一项计算成本,也增加了未来某些时候不一致应用的可能性。

  2. 一旦超过4个字符,字符将在磁盘空间中花费更多(换句话说,12345比“12345”便宜得多)。

  3. 如果您在主键上使用聚簇索引(这是某些RDBM的默认设置),则对字符进行排序与​​排序整数完全不同:

  4. 人物:1,10,101,11,12,13,14,15 ...... 数字:1,2,3,4 ......

    如果您将最大数值作为字符插入,则会破坏索引。这不是一个不可逾越的问题,但更多的是浪费了计算能力来清理。

    至于你关于在PRiMARY KEY上使用LIKE的第二个问题,我想不出你为什么会这样做的原因;如果您需要LIKE的强大功能,通常是因为您为用作PRIMARY KEY的列分配了某种重要性,这意味着您需要将其公开给最终用户。如果是这种情况,那么我将使用代理自动递增数字主键,并向用户公开某种形式的ID。

答案 1 :(得分:1)

1:是的,没关系。也可以在汽车里每小时行驶10英里。汽车不会坏掉。在任何比较中,字符(或varchars)都是低速,因此结果是需要相同性能的更大预算。他们浪费空间,他们很慢。我建议你在这里做唯一明智的事 - 找一个不是白痴的人找工作。

2:甚至不确定。看,这里的问题是 - 这很可能只是你不能使用的东西。如:数据库不允许它。我真的没有尝试过 - 我也不会尝试以每小时100英里的速度撞击一个混凝土块,看它是否会损坏汽车。这没什么意义。

您的首席技术官显然需要休假并阅读一本书。可能有人应该与首席执行官谈谈并将他送到这里 - 他有一个白痴进入CTO职位。

有反对和合成(一个字段)主键的论据,但我从未在25年内与数据库合作,看到有人在DBase或Cobol之外做了。这是一个史诗般的无知。 Pointy Haired老板。

答案 2 :(得分:1)

好吧,你可以做这样的事情(假设SQL 2008 R2 +):

create table dbo.keep_the_peace (
  pk as right(replicate('0',10)+convert(varchar(10),pk_generator),10) persisted not null
, pk_generator int not null identity(1,1) 
, name nvarchar(128) not null
, constraint pk_keep_the_peace primary key nonclustered (pk)
, constraint uc_keep_the_peace unique clustered (pk_generator)
) 
go

insert dbo.keep_the_peace (name) values ('Hello')
insert dbo.keep_the_peace (name) values ('World')

select * from dbo.keep_the_peace

优点:

  1. pk是varchar,CTO可以使用LIKE
  2. pk是自动生成的,无需重新查询插入
  3. 上的表 由于零填充,
  4. pk按正确的顺序排序。
  5. pk_generator可用于外键约束,每个引用可节省6个字节,而CTO仍可加入pk并获得正确的结果。
  6. keep_the_peace上的非聚集索引将享有一个瘦小的聚类键(pk_generator
  7. 缺点:

    1. pk + pk_generator每行使用14个字节,超过必要的10个字节。
    2. pk_keep_the_peace每行使用14个字节,比必要的多14个字节。 (LOL)
    3. 修改

        

      他强烈主张我们使用的是“select * from”   员工@columnName喜欢@value“他这样说,查询   优化者会跑得更好。

      • 没有这样的语法:如果没有动态SQL,则无法参数化列名。
      • 没有这样的好处:每次列名更改时都会生成一个新的执行计划。

      如果WHERE子句中的列发生更改,则会重新编译您的查询。没有办法避免这种情况。列可能以不同方式编制索引。

      例如,对于id上的聚簇索引,这将作为聚簇索引执行:

      select * from employee where id = 6
      

      然而这需要昂贵的表扫描:

      select * from employee where name like 'somename%'
      

      name上放置一个非聚集索引,对于同一个查询,您可以获得更高效的索引搜索+书签查找(通常)。

      INT与CHAR无关。没有。字符键只占用较大的空间(通常),占用空间大,可降低I / O吞吐量。但是这些vanilla查询的性能在很大程度上取决于索引而不是数据类型。