【发布时间】:2017-02-15 04:28:47
【问题描述】:
如果您缺少信息,如果需要,我会附上。
工作区
我有一个在这种 MS SQL 2012 标准版上运行的数据库:
-
表格:
-
用户(id,softId(不唯一),生日)
- 行数:1050 万
- 索引:所有三列,生日(聚集)
-
docs(docId, userId, creationDate, deleteDate, lastname, forename, classificationId)
-
行数:2300 万
-
索引:姓氏、名字、docId、creationDate、userID(clustered)
-
注意:在这种特定情况下,名称与文档相关,而不是与 userId 相关
-
-
分类(id,描述)
- 行数:200
-
三个表“数据”
- 行:10、13 和 30 万行
- 索引:docIds
-
-
关系:
-
用户到文档:1 到 n
-
文档分类:1 到 n
-
文档到数据表:1 到 n
-
要选择完整的记录,我实际上是在以下陈述:
服务器执行时间 16 秒
SELECT * FROM (
select * from docs
where userID in (
select distinct userID from users where softId like '...'
)
) as doc
LEFT JOIN users on users.userID = doc.userId
LEFT JOIN classifications on classifications.id = doc.classificationId
LEFT JOIN data1 on data1.docId = doc.docId
LEFT JOIN data2 on data2.docId = doc.docId
LEFT JOIN data3 on data3.docId = doc.docId;
更新 - 现在 15 秒
SELECT
docID, calssificationId, classificationDescription,
userId, softId, forename, lastname, birthdate,
data1.id, data1.date, data2.id, data2.date, data3.id, data3.date,
FROM docs
JOIN users on users.userID = doc.userId AND softId like '...'
LEFT JOIN classifications on classifications.id = doc.classificationId
LEFT JOIN data1 on data1.docId = doc.docId
LEFT JOIN data2 on data2.docId = doc.docId
LEFT JOIN data3 on data3.docId = doc.docId;
执行计划
服务器执行时间 17 秒
DECLARE @userIDs table( id bigint );
DECLARE @docIDs table( id bigint );
insert into @userIDs select userID from users where softId like '...';
insert into @docIDs select docId from docs where userId in ( select id from @userIDs);
SELECT * FROM users where userID in ( select id from @userIDs);
SELECT * FROM docs where docID in (select id from @docIDs);
SELECT * FROM data1 where data1.docId in (select id from @docIDs);
SELECT * FROM data2 where data2.docId in (select id from @docIDs);
SELECT * FROM data3 where data3.docId in (select id from @docIDs);
GO
更新 - 现在 14 秒
DECLARE @userIDs table( id bigint, softId varchar(12), birthdate varchar(8) );
DECLARE @docIDs table( id bigint, classification bigint, capture_date datetime, userId bigint, lastname varchar(50), forename varchar(50) );
INSERT INTO @userIDs select userID, softId, birthdate from users where softId like '...';
INSERT INTO @docIDs select docID, classification, capture_date, userID, lastname, forename from docs where userID in ( select id from @userIDs);
SELECT * FROM @userIDs;
SELECT * FROM @docIDs;
SELECT [only needed fields] FROM data1 where docID in (select id from @docIDs);
SELECT [only needed fields] FROM data2 where docID in (select id from @docIDs);
SELECT [only needed fields] FROM data3 where docID in (select id from @docIDs);
执行计划
一般更新 @AntonínLejsek 建议将文档的 docId 定义为聚集索引,将 pkId 定义为非聚集索引。这改变了执行时间如下:
- 加入声明:-1 秒
- 多选语句:-5 秒
我再次检查了索引并更改了包含的列,现在它们有了执行时间:
- 加入声明:4 秒
- 多选语句:6 秒
“简单”问题
有人有减少执行时间的建议吗?
【问题讨论】:
-
亲爱的,第一个:为什么在您的子查询中使用 distinct 从 softId 像“...”的用户中选择不同的用户 ID。 userID 不是 users 表的主键?
-
@JoeTaras :你是对的,不需要区分。我删除了它,但它没有影响。
-
这里是
select *合适还是您只需要检索特定字段?可以发一下执行计划吗? -
@alroc 我通过更改其他内容减少了字段数量,但没有更改帖子,抱歉 - 执行计划现在已链接
标签: sql sql-server performance sql-server-2012