1

嗯,我对数据库架构了解不多,但我真的不明白 CTO 的想法,但他坚持使用字符作为我们使用的所有表的主键的列类型。但是主键仍然看起来像这样 - > 1,2,3...等等。它们是数字的。所以我使用整数 + auto_increment 合成 PK

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

  1. PK 使用字符是否可以,尤其是当您的 PK 是数字时?
  2. 在PK上使用like条件是否正确?

PS - 因此,序列 CTO 不是自动递增/触发,而是发出选择查询,从表中获取最大值,然后加 1,然后将该值转换为字符串,然后存储它。

编辑
感谢您的帮助!但我需要让他相信这将是一场灾难。我只被告知这(在这种情况下为字符 4 PK)是一个坏主意。他的论点是……
1、角色PK不会占用太多空间。
2. 如果您使用 int 类型 PK,数据库查询优化器将不得不重新读取您的查询,因为您将不得不发出类似
"select * from employee where name like 'somename'
and的问题
Select * from employee where id = 6
因为 where 子句发生了变化。
他强烈认为我们使用的东西就像
"select * from employee where @columnName like @value"
他说的那样,查询优化器会运行得更好。

我怎样才能证明或给他一些改变主意的正当理由?

谢谢 : )

4

3 回答 3

4

您的 CTO 在该决定上犯错的原因有很多;让我介绍几个:

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

  2. 一旦超过 4 个字符,字符将占用更多的磁盘空间(换句话说,存储 12345 比“12345”便宜很多)。

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

字符:1、10、101、11、12、13、14、15... 数字:1、2、3、4...

如果您将最大数值作为字符插入,则您正在粉碎您的索引。不是无法克服的问题,而是更多的浪费算力去清理。

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

于 2013-01-07T03:18:15.003 回答
1

1:是的,没关系。开车总是以每小时 10 英里的速度行驶也是可以的。这辆车不会抛锚。Chars(或 varchars)在任何比较中都比较慢,因此结果是需要更大的预算才能获得相同的性能。他们浪费空间,他们很慢。我建议你在这里做唯一明智的事情——找一个不是白痴的工作。

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

您的 CTO 显然需要休假并阅读一本书。可能有人应该与 CEO 谈谈并将他派到这里来——他让一个白痴进入了 CTO 的位置​​。

有反对和支持合成(一个字段)主键的论点,但在我使用数据库的 25 年中,我从未见过有人在 DBase 或 Cobol 之外这样做。这是史诗般的无知。尖头发的老板。

于 2013-01-07T03:12:25.620 回答
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. pk由于零填充,以正确的顺序排序。
  4. pk_generator可以在外键约束中使用,每个引用节省 6 个字节,而 CTO 仍然可以加入pk并获得正确的结果。
  5. 上的非聚集索引keep_the_peace将享受瘦聚集键 ( pk_generator)

缺点:

  1. pk+pk_generator每行使用 14 个字节,超过必要的 10 个。
  2. pk_keep_the_peace每行使用 14 个字节,超过必要的 14 个字节。(哈哈)

编辑

他强烈认为我们使用的是“select * from employee where @columnName like @value”。他这样说,查询优化器会运行得更好。

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

如果WHERE子句中的列发生变化,那么是的,您的查询将被重新编译。没有办法避免这种情况。列的索引可能不同。

例如,使用聚集索引 on id,这将作为聚集索引搜索执行:

select * from employee where id = 6

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

select * from employee where name like 'somename%'

将非聚集索引放在 上name,对于相同的查询,您可以获得更有效的索引查找 + 书签查找(通常)。

INT vs CHAR 与它无关。没有。字符键只是占用较大的空间(通常),而较大的占用空间会降低 I/O 吞吐量。但是这些普通查询的性能将更多地取决于索引而不是数据类型。

于 2013-01-07T03:58:37.113 回答