我将传感器数据存储在表SensorValues 中。表和主键如下:
CREATE TABLE [dbo].[SensorValues](
[DeviceId] [int] NOT NULL,
[SensorId] [int] NOT NULL,
[SensorValue] [int] NOT NULL,
[Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED
(
[DeviceId] ASC,
[SensorId] ASC,
[Date] DESC
) WITH (
FILLFACTOR=75,
DATA_COMPRESSION = PAGE,
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
ON [MyPartitioningScheme]([Date])
Run Code Online (Sandbox Code Playgroud)
然而,当我选择在特定时间有效的传感器值时,执行计划告诉我它正在执行排序。这是为什么?
我原以为,由于我存储了按日期列排序的值,因此不会发生排序。还是因为索引不仅仅按日期列排序,即它不能假设结果集已排序?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = …
Run Code Online (Sandbox Code Playgroud) 这是主键中指定的排序顺序的衍生问题,但排序是在 SELECT 上执行的。
@Catcall关于存储顺序(聚集索引)和输出顺序的主题
很多人认为聚集索引可以保证输出的排序顺序。但这不是它的作用。它保证了磁盘上的存储顺序。 例如,请参阅此博客文章。
我已经阅读了 Hugo Kornelis 的博客文章,并了解到索引并不能保证 sql server 以特定顺序读取记录。然而,我很难接受我不能为我的场景假设这一点?
CREATE TABLE [dbo].[SensorValues](
[DeviceId] [int] NOT NULL,
[SensorId] [int] NOT NULL,
[SensorValue] [int] NOT NULL,
[Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED
(
[DeviceId] ASC,
[SensorId] ASC,
[Date] DESC
) WITH (
FILLFACTOR=75,
DATA_COMPRESSION = PAGE,
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
ON …
Run Code Online (Sandbox Code Playgroud) 为了清楚起见,在 2012-06-20 重写了这个问题,检查旧版本的编辑
我为某些设备上的几个传感器收集数据。我想在图形中以曲线的形式为用户显示这些数据,即我想绘制测量点并在它们之间画线。用户可以通过在图表中缩放和平移来决定他想要显示值的日期范围。
测量值的数量开始增加,此时我有许多值在500'000'000范围内,并且还在计数。对于单个传感器,到目前为止,我最多可以找到大约2'000'000 个值,但它很可能会增加。这些值不是以均匀间隔(即每秒)记录的,而是在可以测量更改时记录的(请参阅下面日期列中的差异)。
Date SensorValue
----- -----------
10 123
30 118
70 114
85 115
90 116
95 117
Run Code Online (Sandbox Code Playgroud)
由于此图形的显示区域为1000 像素,因此获取所有这些值毫无意义。相反,我尝试获取最多1000 个值,并将它们均匀分布在用户放大的日期范围内。确切地返回日期范围内的哪些值并不重要,只要它们在日期方面均匀分布(记住这一点很重要,因为它们不是以均匀间隔记录的)。
我将这些值存储在一个非常简单的表中,如下所示,只有一个(聚集)索引。请注意,Date
存储为整数(“unix 时间”)而不是datetime2
字段。该表按Date
是否重要进行分区。
CREATE TABLE [dbo].[SensorValues](
[DeviceId] [int] NOT NULL,
[SensorId] [int] NOT NULL,
[SensorValue] [int] NOT NULL,
[Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED
(
[DeviceId] ASC,
[SensorId] ASC,
[Date] DESC
);
Run Code Online (Sandbox Code Playgroud)
我正在寻找两件事之一,要么是一个改进的查询,它可以更快地返回这些值,要么 …
背景
我有几个设备,每个设备都有几个传感器。我不时地记录这些并将它们存储在下面描述的表中。当有人请求一个网页时,我会一个接一个地获取这些值中的几个(最新记录的)并将它们显示给用户。但是目前这需要很长时间,因为需要提取的值太多,每个值的提取需要大约 8 毫秒,并且我们总共讨论了大约 300 毫秒的总页面加载时间增加 - 对于一个相对较好的页面。
CREATE TABLE [dbo].[SensorValues](
[DeviceId] [int] NOT NULL,
[SensorId] [int] NOT NULL,
[SensorValue] [int] NOT NULL,
[Date] [int] NOT NULL, --- stored as unixtime
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED
(
[DeviceId] ASC,
[SensorId] ASC,
[Date] DESC
);
Run Code Online (Sandbox Code Playgroud)
该表在日期列上每周进行分区。
我现在应该做什么
所以,我做的是以下。我选择每个分区中当前日期/时间之前的最大值。并选出最大的值。
SELECT TOP (1) ca.SensorValue, ca.Date
FROM sys.partitions AS p
CROSS APPLY
(
SELECT TOP (1) v.Date, v.SensorValue
FROM SensorValue AS v
WHERE $PARTITION.SensorValues_Date_PF(v.Date) = p.[partition_number]
AND v.DeviceId = @fDeviceId
AND v.SensorId = @fSensorId …
Run Code Online (Sandbox Code Playgroud) 我正在检查一个 SQL Server 2008R2 安装有很大的性能问题。目前我正在查看它的索引和外键,发现没有一个表指定了任何外键。要么应用程序自己处理所有业务逻辑,要么安装错误。
外键对性能的影响有多大?还是它们只存在于业务逻辑?是否有没有外键是优势的情况?(例如本系统支持 SQL Server、Oracle 和 DB2。)
我有一个大的分区时间序列表,其中每个分区都存储在它自己的文件中。由于它是基于时间序列的分区按周划分,而且我只存储新数据,因此我一次积极写入的分区不超过 2 个。我在索引上将 FILLFACTOR 设置为 75,因为数据是随机输入的。
旧的数据分区占用了相当多的空间,仅使用了大约 60-70% 的空间。是否可以自动更改所述分区上的 FILLFACTOR,重建索引并缩小文件?由于我不再写入这些分区,因此它们的大小不应再增长。
sql-server ×5
partitioning ×2
fill-factor ×1
foreign-key ×1
group-by ×1
performance ×1
primary-key ×1
select ×1
shrink ×1
sorting ×1