从数学的角度来看,假设一个表最多有一个主键,通过任意名称而不是简单的表属性来引用主键似乎是一种短视的设计决定。
因此,要将主键从非集群更改为集群,反之亦然,您必须首先搜索其名称,而不是删除它并最终读取它。
使用我看不到的任意名称是否有一些优势,或者 DBMS 是否不使用任意名称作为主键?
编辑 2011-02-22 (对于那些不想在那里排序的人,2011 年 2 月 22 日):
让我展示一个函数,您可以使用它从表名中导出主键的名称(使用早期的 sql-sever 又名 sybase 系统表):
create function dbo.get_pk (@tablename sysname)
returns sysname
as
begin
return (select k.name
from sysobjects o
join sysobjects k on k.parent_obj = o.id
where o.name = @tablename
and o.type = 'U'
and k.type = 'k')
end
go
Run Code Online (Sandbox Code Playgroud)
正如 gbn 所说,当您不提供明确的名称时,没有人真正喜欢生成的名称:
create table example_table (
id int primary key
)
select dbo.get_pk('example_table')
Run Code Online (Sandbox Code Playgroud)
我刚得到
PK__example___3213E83F527E2E1D
Run Code Online (Sandbox Code Playgroud)
但是为什么 sysobjects 中的名称必须是唯一的。对表及其主键使用完全相同的名称是完全可以的。
这样做,我们不需要设置命名约定,这可能会被意外违反。
现在回答玛丽安:
TL; DR:
插入大量的行的无冲突快得多比(不)重新插入相同的行,BOTH使用INSERT IGNORE语法。
为什么是这样?我假设插入和“忽略”插入的索引查找成本相同,因为 MySQL 不知道传入的数据是否具有重复/冲突的数据(因此需要被忽略)......因此,索引发生在初始插入和被忽略的插入运行中。
此外,我认为“忽略”行应该是便宜的,因为它不需要任何磁盘写入。
但这绝对不是这种情况。
长版:
在这个问题中,我们使用 AWS 的 Aurora/MySQL 和LOAD DATA FROM S3 FILE语法来删除任何传输或性能变量。我们加载了一个与下面架构相对应的 4 兆行 CSV 文件,并加载了两次,每次都使用LOAD ... IGNORE.
请注意,该问题也发生在标准INSERT ... IGNORE,但使用批量行插入时。LOAD ... IGNORE这里的用途是将讨论引向测量结果的反直觉性质,而不是“如何执行大量被忽略的插入”。这不是这里的问题,因为已经制定了特定于域的方法。
在被测试的模型中,有一个三层索引:前两个是基数非常低的可枚举分类列,第三个列本质上是“实际”数据。为了简化这个问题,我只是坚持我目前的设置。
假设以下简单模式:
our_table:
id: basic auto-increment bigint, primary key
constkey1: varchar(50) -- this is a constant in the insert
constkey2: varchar(50) -- this is a constant in the insert
datakey: varchar(50) -- this is pulled in …Run Code Online (Sandbox Code Playgroud)