我对这个想法进行了一些确认,以修复性能不佳的数据库或更好的建议(如果有人有的话)。始终对更好的建议持开放态度。
我有一个非常大的数据库(20 多万条记录,每天增长约 1/2 百万),它使用 GUID 作为 PK。
我的疏忽,但 PK 聚集在 SQL 服务器上并导致性能问题。
guid 的原因 - 此数据库与 150 个其他数据库部分同步,因此 PK 需要是唯一的。同步不是由 SQL Server 管理的,而是构建了一个自定义过程,使数据保持同步以满足系统的要求——所有这些都基于该 GUID。
150 个远程数据库中的每一个都不存储中央 SQL 数据库中存储的完整数据。他们只存储他们实际需要的数据的一个子集,并且需要的数据对他们来说不是唯一的(150 个数据库中有 10 个可能有一些来自其他站点数据库的相同记录,例如 - 他们共享)。此外 - 数据实际上是在远程站点生成的 - 而不是在中心点 - 因此需要 GUID。
中央数据库不仅用于保持所有内容同步,而且将针对这个非常大的碎片数据库执行来自 3000 多个用户的查询。这在初始测试中已经是一个大问题。
幸运的是,我们还没有上线 - 所以我可以进行更改并在需要时将事情脱机,这至少是一些事情。
远程数据库的性能不是问题 - 数据子集非常小,数据库的总大小通常不会超过 1GB。记录会定期反馈到主系统,并在不再需要时从较小的 BD 中删除。
作为所有记录的管理员的中央数据库的性能是可悲的 - 由于聚集的 GUID 作为许多记录的主键。索引碎片不在图表之列。
所以 - 我解决性能问题的想法是创建一个新列 - Unsigned BIGINT IDENTITY(1,1) 然后更改表 BIGINT 列的 Clustered PK。
我会在作为主键的 GUID 字段上创建一个唯一的非聚集索引。
较小的远程 150 数据库不需要知道中央 SQL Server 数据库上的新 PK …
我有一个包含四列的表,这些列都是不可为空的,并且数据是这样的,需要所有四列来区分唯一记录。这意味着如果我要创建一个主键,它需要包含所有列。对表的查询几乎总是拉回单个记录,即所有列都将在查询中被过滤。
由于需要搜索每一列,拥有主键对我有好处吗(除了强制记录的唯一性)?
我知道两者之间的含义或意图可能有所不同,但是聚集主键和聚集唯一索引之间是否存在任何行为或性能差异?
我在将日期时间(甚至日期)作为主键的第一部分进行索引时遇到问题。
我使用 MySQL 5.5
这是我的两个表:
-- This is my standard table with dateDim as a dateTime
CREATE TABLE `stats` (
`dateDim` datetime NOT NULL,
`accountDim` mediumint(8) unsigned NOT NULL,
`execCodeDim` smallint(5) unsigned NOT NULL,
`operationTypeDim` tinyint(3) unsigned NOT NULL,
`junkDim` tinyint(3) unsigned NOT NULL,
`ipCountryDim` smallint(5) unsigned NOT NULL,
`count` int(10) unsigned NOT NULL,
`amount` bigint(20) NOT NULL,
PRIMARY KEY (`dateDim`,`accountDim`,`execCodeDim`,`operationTypeDim`,`junkDim`,`ipCountryDim`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
-- Here is a copy with datDim as an integer
CREATE TABLE `stats_todays` (
`dateDim` …Run Code Online (Sandbox Code Playgroud) 我有以下表格和索引定义:
CREATE TABLE munkalap (
munkalap_id serial PRIMARY KEY,
...
);
CREATE TABLE munkalap_lepes (
munkalap_lepes_id serial PRIMARY KEY,
munkalap_id integer REFERENCES munkalap (munkalap_id),
...
);
CREATE INDEX idx_munkalap_lepes_munkalap_id ON munkalap_lepes (munkalap_id);
Run Code Online (Sandbox Code Playgroud)
为什么在以下查询中没有使用 munkalap_id 上的任何索引?
EXPLAIN ANALYZE SELECT ml.* FROM munkalap m JOIN munkalap_lepes ml USING (munkalap_id);
QUERY PLAN
Hash Join (cost=119.17..2050.88 rows=38046 width=214) (actual time=0.824..18.011 rows=38046 loops=1)
Hash Cond: (ml.munkalap_id = m.munkalap_id)
-> Seq Scan on munkalap_lepes ml (cost=0.00..1313.46 rows=38046 width=214) (actual time=0.005..4.574 rows=38046 loops=1)
-> Hash (cost=78.52..78.52 rows=3252 …Run Code Online (Sandbox Code Playgroud) 我有一份死锁报告,告诉我有一个涉及到的冲突
waitresource="KEY: 9:72057632651542528 (543066506c7c)"
Run Code Online (Sandbox Code Playgroud)
我可以看到这个:
<keylock hobtid="72057632651542528" dbid="9" objectname="MyDatabase.MySchema.MyTable" indexname="MyPrimaryKeyIndex" id="locka8c6f4100" mode="X" associatedObjectId="72057632651542528">
Run Code Online (Sandbox Code Playgroud)
该范围内<resource-list>的元素。
我希望能够找到键的实际值(例如,id = 12345)。我需要使用什么 SQL 语句来获取该信息?
为两列或更多列创建复合主键时,例如PRIMARY KEY(col1, col2, col3);系统将INDEX每列单独?
我问这个问题的原因是,当我们使用 时UNIQUE INDEX (col1, col2, col3),它INDEX仅作为第一列,我们需要INDEX为其他列创建额外的s。我想知道复合主键是否也是这种情况。
我正在构建一个 Web 应用程序(项目管理系统),并且在性能方面我一直对此感到疑惑。
我有一个问题表,里面有 12 个外键链接到各种其他表。其中,我需要加入其中的 8 个以从其他表中获取标题字段,以便记录在 Web 应用程序中有意义,但这意味着进行 8 个连接,这似乎非常多,尤其是因为我只是在拉入每个连接有 1 个字段。
现在我还被告知要使用自动递增的主键(除非分片是一个问题,在这种情况下我应该使用 GUID)出于永久性原因,但是使用 varchar(最大长度 32)性能有多糟糕?我的意思是这些表中的大多数可能不会有很多记录(其中大多数应该低于 20)。此外,如果我使用标题作为主键,我将不必在 95% 的时间内进行连接,因此对于 95% 的 sql,我什至会发生任何性能下降(我认为)。我能想到的唯一缺点是我的磁盘空间使用量会更高(但一天下来真的很重要)。
我使用查找表来代替枚举的原因是因为我需要最终用户通过应用程序本身来配置所有这些值。
使用 varchar 作为表的主键的缺点是什么,除非有很多记录?
更新 - 一些测试
所以我决定对这些东西做一些基本的测试。我有 100000 条记录,这些是基本查询:
基本 VARCHAR FK 查询
SELECT i.id, i.key, i.title, i.reporterUserUsername, i.assignedUserUsername, i.projectTitle,
i.ProjectComponentTitle, i.affectedProjectVersionTitle, i.originalFixedProjectVersionTitle,
i.fixedProjectVersionTitle, i.durationEstimate, i.storyPoints, i.dueDate,
i.issueSecurityLevelId, i.creatorUserUsername, i.createdTimestamp,
i.updatedTimestamp, i.issueTypeId, i.issueStatusId
FROM ProjectManagement.Issues i
Run Code Online (Sandbox Code Playgroud)
基础 INT FK 查询
SELECT i.id, i.key, i.title, ru.username as reporterUserUsername,
au.username as assignedUserUsername, p.title as projectTitle,
pc.title as …Run Code Online (Sandbox Code Playgroud) 我通过一个复杂的选择查询创建了表CREATE TABLE ... AS SELECT...。如何在此查询中添加自动增量主键?
例如:
create table `user_mv` select `user`.`firstname` as
`firstname`,
`user`.`lastname` as `lastname`,
`user`.`lang` as `lang`,
`user`.`name` as `user_name`,
`group`.`name` as `group_name`
from `user`
inner join `user_groups` on (`user`.`user_id`=`user_groups`.`user_id`)
left join `group` on (`group`.`group_id`=`user_groups`.`group_id`)
where `user`.`lang`=`group`.`lang`
Run Code Online (Sandbox Code Playgroud)
此查询创建一个包含firstname, lastname, lang, username,group_name列的表。我希望它也有一个id作为自动增量主键的列。
有没有办法通过更改此查询来做到这一点?我知道我可以通过在执行此查询后更改表来做到这一点,但是如果有任何方法可以直接在create table语句中执行此操作,我想知道如何执行此操作。
我正在开发一个 SQL Server 2012 数据库,我对 nvarchar 列作为主键有疑问。
我有这张桌子:
CREATE TABLE [dbo].[CODES]
(
[ID_CODE] [bigint] IDENTITY(1,1) NOT NULL,
[CODE_LEVEL] [tinyint] NOT NULL,
[CODE] [nvarchar](20) NOT NULL,
[FLAG] [tinyint] NOT NULL,
[IS_TRANSMITTED] [bit] NOT NULL DEFAULT 0,
CONSTRAINT [PK_CODES] PRIMARY KEY CLUSTERED
(
[CODE_LEVEL] ASC,
[CODE] ASC
)
)
Run Code Online (Sandbox Code Playgroud)
但现在我想使用[CODE]列作为主键并删除[ID_CODE]列。
如果我有一个NVARCHAR专栏,有什么问题或惩罚PRIMARY KEY吗?
[CODE]列值必须是唯一的,所以我认为我可以UNIQUE为该列设置约束。
我是否必须用[CODE]作主键,还是UNIQUE在[CODE]列上设置约束更好?
primary-key ×10
index ×4
mysql ×4
sql-server ×3
performance ×2
ctas ×1
deadlock ×1
innodb ×1
join ×1
mysql-5.5 ×1
postgresql ×1
select ×1