我刚刚参与了一个项目,我必须在该项目上开发一个数据迁移过程和一个使用现有 SQL Server 数据库的 Web 界面。这个数据库是几年前由另一个人开发的,它有大约 100 GB 的数据,并且每 10 分钟增加一次(它存储来自多个单元的 10 分钟数据 -> 每个设备每天 144 条记录)。几个表有大约 1000 万行。关键是我认为主表的设计方式不是最有效或最适合通常执行的查询类型的方式。现在我需要证明我所说的是否比已经实施的更好。DB 表的数量很庞大,但可以通过下图简化结构:

Date_Id 字段由使用 DateTime 字段的函数自动生成。两个表中都有两个索引。每个表的簇索引包含相同顺序的 PK 字段。Unit 表的第二个索引仅包含 Unit_Id 字段,而 UnitData 中的第二个索引按此顺序包含 Unit_Id 和 DateTime 字段。
但是,我认为设计应该是这样的:

在这种情况下,只需要 PK 字段的聚集索引。对于此数据库设计,通常的查询类似于:
SELECT ud.*
FROM Unit u, UnitData ud
WHERE u.Unit_Id = ud.Unit_Id and ud.DateTime >= 'dd-MM-yyyy'
ORDER BY ud.Unit_Id, ud.DateTime
Run Code Online (Sandbox Code Playgroud)
现在出现了我真的不明白的事情:有人告诉我,拥有 Date_Id 列的唯一原因是将其用作该表的分区列。我问过对这个表进行分区的真正必要性,答案是“在需要每日或每月数据时更有效地运行查询”。在此之前我不太了解分区,所以我检查了这些链接:
http://msdn.microsoft.com/en-us/library/ms190787.aspx
考虑到理想的查询是按设备和日期时间过滤,问题是:
非常感谢!!
我使用以下查询来查找查询中的性能改进:
SELECT TOP 20 SUBSTRING(qt.text, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(qt.text)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2)+1),
qs.execution_count,
qs.total_logical_reads, qs.last_logical_reads, qs.min_logical_reads,
qs.max_logical_reads, qs.total_physical_reads, qs.last_physical_reads,
qs.min_physical_reads, qs.max_physical_reads,
qs.total_elapsed_time / 1000000 As total_elapsed_time,
qs.last_elapsed_time / 1000000 As last_elapsed_time,
qs.min_elapsed_time / 1000000 As min_elapsed_time,
qs.max_elapsed_time / 1000000 As max_elapsed_time,
qs.last_execution_time, qs.creation_time, qp.query_plan
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
WHERE qt.encrypted=0
AND last_execution_time >= DATEADD (MINUTE , -5 , CURRENT_TIMESTAMP )
ORDER BY qs.total_logical_reads DESC
--ORDER BY qs.total_physical_reads DESC …Run Code Online (Sandbox Code Playgroud) performance sql-server users query-performance performance-tuning
我试图弄清楚为什么在 SQL Server 中,两个相同的查询在两个几乎相同的索引下执行时花费的时间略有不同。提到的查询非常简单,具有以下形状>
set statistics io on
set statistics time on
SELECT t.field3
FROM Table t --WITH(INDEX(Index2))
WHERE t.field1 = 6 AND t.field2 = 'B'
AND t.field3 >= CAST ('01-07-2012' As DateTime) AND t.field3 < CAST ('01-10-2012' As DateTime)
ORDER BY t.field3
Run Code Online (Sandbox Code Playgroud)
如果我在 Table t(包含 52M 行)上运行此查询,则检索到的统计信息为:
如果我检查查询的实际执行计划,它会在 Index1 上显示 100% 的 Index Seek,它是非聚集的,并按此顺序包含字段 field1、field2、field3。但是,如果我取消注释强制使用 Index2 的行,它包含相同顺序的相同字段,但它是聚集的(主键),统计信息是:
虽然花费的总时间并没有特别糟糕,但我想了解这里发生了什么。谁能给我一个解释?除了时差很小之外,还有性能差异吗?
非常感谢 !!
我在 SQL Server 中运行以下(非常简单)查询:
SELECT MAX(PK_Field1)
FROM MainTable kh
WHERE kh.PK_Field1 >= '2014-12-01T00:00:00'
AND kh.PK_Field2 = 1572
AND kh.PK_Field3= 'FD5BF2F3-8ED7-479C-A71F-D04E4288CBFC'
Run Code Online (Sandbox Code Playgroud)
我从中得到了这些统计数据:
Table 'MainTable'. Scan count 9, logical reads 31078, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 171 ms, elapsed time = 44 ms.
Run Code Online (Sandbox Code Playgroud)
虽然经过的时间并不多,但这个查询每十分钟执行大约一千次,所以超过 30k 的逻辑读取对我来说似乎不是很理想。但是,该表中的主索引的设计方式使这样的查询可以充分利用它。表 MainTable 包含以下内容:
PK_Field1 datetime
PK_Field2 int
PK_Field3 uniqueidentifier
Another_Field datetime
Run Code Online (Sandbox Code Playgroud)
该表不包含其他列,它有 300 万条记录,唯一的索引是 PK 字段上的聚集索引(与表中定义的顺序相同,按 ASC …
我已经处理了很长时间的 MS SQL Server 日期时间类型,但从未想过为什么会发生以下情况:
yyyy-MM-dd hh:mm:ssWHERE TimeStamp >= 'yyyy-MM-dd hh:mm:ss'似乎只有当我更改指定的格式并使用欧洲格式编写它时才有效,例如WHERE TimeStamp >= 'dd-MM-yyyy hh:mm:ss'. 为什么 SQL Server 以一种在应用于自身时不可覆盖或有效的格式向我显示日期?我在编写查询时更改日期格式没有任何问题,但我想在应用程序级别(Java-JDBC 应用程序)使用这些日期,并且我不想一直应用日期格式更改。 .. 谁能解释一下为什么会发生这种情况,以及是否有任何方法可以在数据库级别解决它?谢谢!!
编辑:请参阅下面 Management Studio 中错误的屏幕截图。

这应该是一个非常简单的查询,但老实说,我认为它的执行时间可以改进。
select idTag,MAX(pctimestamp) AS PCTIMESTAMP,getdate() AS NOW, datediff(SECOND,MAX(pctimestamp),getdate()) AS DELAY
from ValuesTagsOPC
group by IdTag
Run Code Online (Sandbox Code Playgroud)
此查询从“ValuesTagsOPC”表返回 1386 行,该表包含大约 4000 万行,并具有以下结构,由创建脚本检索:
CREATE TABLE [dbo].[ValuesTagsOPC](
[IdTag] [int] NOT NULL,
[TTimeStamp] [datetime] NOT NULL,
[PCTimeStamp] [datetime] NOT NULL,
[Value] [nvarchar](50) NOT NULL,
[Quality] [int] NOT NULL,
CONSTRAINT [PK_ValuesTagsOPC] PRIMARY KEY CLUSTERED
(
[IdTag] ASC,
[PCTimeStamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
很明显,它的主键上有一个聚集索引。SQL Server 的时间和 IO 统计信息如下(抱歉,它是西班牙语):
(1386 …Run Code Online (Sandbox Code Playgroud) sql-server ×6
performance ×5
date-format ×1
datetime ×1
optimization ×1
partitioning ×1
users ×1