围绕表分区的一般问题。如果您在 Date 列上对表进行分区,并且每个 RANGE 为 12 个月。
如果您要插入之前的分区周期,与插入当前分区相比,您是否期望性能会变慢?
围绕表分区的一般问题。如果您在 Date 列上对表进行分区,并且每个 RANGE 为 12 个月。
如果您要插入之前的分区周期,与插入当前分区相比,您是否期望性能会变慢?
这是几年前这个问题的后续,在 SQL 2014 中拆分现有分区,现在从 2011 年一直到 2021 年都有分区年。
我需要通过将数据从这些分区移动到新的表/数据库来归档分区 2011 到 2015,然后归档这个数据库,并从原始日志表中删除 2011 到 2015 的分区。
我使用以下语句成功地将数据移出到 Log_Archive 表中。
ALTER TABLE dbo.Log
SWITCH PARTITION $PARTITION.pfYearlyPartition_Log('20120101')
TO dbo.Log_Archive PARTITION $PARTITION.pfYearlyPartition_Log_Archive('20120101');
我不确定现在如何从 Log 表中删除该分区,因为它仍然存在但其中包含 0 行。有人可以建议吗?您可以在下面看到我已成功将数据从 Log 移动到 Log_Archive 但我在原始 Log 表中留下了 0 行要删除的行。
我希望我不需要重新分区整个表,因为它非常大。
我在表上有以下分区设置。
我想创建一个从 2019-01-01 开始的新分区。
这是正确的做法吗?它现在可以运行吗,以便为 2019 年做好准备?
ALTER DATABASE mydatabase ADD FILEGROUP [Year7FileGroup]
GO
ALTER DATABASE mydatabase
ADD FILE
(NAME = N'data_year7',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.SQL2014\MSSQL\DATA\data_year73.ndf',
SIZE = 5000MB,
FILEGROWTH = 500MB)
TO FILEGROUP [Year7FileGroup]
GO
ALTER PARTITION SCHEME psYearlyPartition_Log
NEXT USED Year7FileGroup;
ALTER PARTITION FUNCTION pfYearlyPartition_Log()
SPLIT RANGE('20190101');
我有一个包含超过 200 亿行的 SQL Server 表,最后一个分区中有 130 亿行。
该表目前按“时间”字段分为 6 种方式:
2011
2012
2013
2014
2015
2016/2017/2018
2016/2017/2018分区需要拆分成各自的分区所以就有了2016、2017、2018分区。
如何做到这一点并在此过程中避免大量日志文件增长?数据库处于简单恢复中,目前每个分区都在其自己的一组磁盘上的单独文件组中。
CREATE TABLE [dbo].[Log](
[RefNo] [nchar](7) NOT NULL,
[DevID] [nvarchar](7) NOT NULL,
[Time] [datetime] NOT NULL,
[summary] [float] NULL,
[staging] [float] NULL,
[position] [float] NULL,
CONSTRAINT [PK_Log] PRIMARY KEY CLUSTERED
(
[RefNo] ASC,
[DevID] ASC,
[Time] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 96)
)
我最近读了这篇关于与函数有关的性能问题的文章。
我目前正处于 Azure SQL 数据库平台上新数据库的开发阶段。它不会在新的几个月内上线。我正在使用各种标量值函数,其中一个是将 UTC 转换为在配置表中指定的本地日期,例如澳大利亚东部标准时间
该函数被调用如下:
SELECT
dbo.fnGetLocalDate(DateColumn) as DateColumn,
FROM
table
在这种情况下,有没有人对如何避免功能有任何建议?我发现它们对代码重用很有用,我不确定如何在这里避免它。
我还想知道 vNext 是否解决了 Azure 平台中函数的性能问题,我最好还是继续使用函数。
CREATE FUNCTION [dbo].[fnGetLocalDate]
(
@DateToConvert datetimeoffset = NULL
)
RETURNS datetimeoffset
AS
BEGIN
DECLARE @TimeZone varchar(50)
RETURN
CASE
WHEN @DateToConvert is NULL then NULL
ELSE
CONVERT(datetimeoffset, @DateToConvert AT TIME ZONE (SELECT Value FROM LookUp.Config WHERE Property = 'TimeZone'))
END
END
我有以下查询:
ALTER PROCEDURE [dbo].[spSearchClient]
@SearchWords NVARCHAR(MAX) = NULL,
@LowerDate DATE = NULL,
@UpperDate DATE = NULL,
@UserCreated nvarchar(450)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @UserAccountID smallint
DECLARE @SearchWordCount int
SELECT @UserAccountID = dbo.fnGetUserAccountID(@UserCreated)
CREATE TABLE #SearchWords
(
ID int IDENTITY(1,1),
Word NVARCHAR(50)
)
INSERT INTO #SearchWords
(
Word
)
SELECT
value
FROM
STRING_SPLIT(@SearchWords, ' ')
WHERE
TRIM(value) <> ''
SELECT @SearchWordCount = @@ROWCOUNT;
SELECT
C.ClientID,
C.FirstName,
C.LastName,
C.FullName,
C.DateOfBirth,
G.GenderName,
G.GenderIcon,
C.VerificationCode,
V.LastVisitDate
FROM
Client C
OUTER APPLY (
SELECT MAX(StartDate) AS LastVisitDate
FROM Visit AS V
WHERE C.ClientID = V.ClientID
) AS V
INNER JOIN LookUp.Gender G on
C.GenderID = G.GenderID
WHERE
(
EXISTS( -- if we have words
SELECT *
FROM #SearchWords s
WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
)
OR @SearchWordCount = 0 --if we don't have words
)
AND DateOfBirth BETWEEN ISNULL(@LowerDate,DateOfBirth) AND ISNULL(@UpperDate,DateOfBirth)
INSERT INTO UserSearchLog
(
SearchWords,
LowerDate,
UpperDate,
SearchResultsCount,
UserCreated
)
VALUES
(
@SearchWords,
@LowerDate,
@UpperDate,
@@ROWCOUNT,
@UserAccountID
)
DROP TABLE #SearchWords
END
执行计划是https://www.brentozar.com/pastetheplan/?id=BkGzfUeHz
该查询按应有的方式工作,但需要 3-7 秒才能运行,这似乎都是由于以下原因,它对 Client 表中的每一行都有一个执行:
WHERE
(
EXISTS( -- if we have words
SELECT *
FROM #SearchWords s
WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
)
OR @SearchWordCount = 0 --if we don't have words
)
想知道是否有人知道一种更好更有效的方法,而且耗时更少?
如果一些样本数据有用,请告诉我。
这是我的头,但我坚持尝试在此查询中的 MAX 聚合上获取索引查找。
这是执行计划——我想知道我在这里遗漏了什么,因为目前查询需要 3/4 秒才能完成,这太慢了。我已经在 StartDate, ClientID 上建立了索引,但没有成功。
CREATE TABLE #SearchWords
(
ID int IDENTITY(1,1),
Word NVARCHAR(50)
)
INSERT INTO #SearchWords
(
Word
)
SELECT
value
FROM
STRING_SPLIT(@SearchWords, ' ')
WHERE
TRIM(value) <> ''
SELECT
C.ClientID,
C.FirstName,
C.LastName,
C.FullName,
C.DateOfBirth,
G.GenderName,
G.GenderIcon,
C.VerificationCode,
MAX(V.StartDate) as LastVisitDate
FROM
Client C
LEFT JOIN Visit V on
C.ClientID = V.ClientID
INNER JOIN LookUp.Gender G on
C.GenderID = G.GenderID
WHERE
(
EXISTS( -- if we have words
SELECT *
FROM #SearchWords s
WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
)
OR
(SELECT COUNT(*) FROM #SearchWords)=0 -- if we haven't any words
)
AND DateOfBirth BETWEEN ISNULL(@LowerDate,DateOfBirth) AND ISNULL(@UpperDate,DateOfBirth)
GROUP BY
C.ClientID,
C.FirstName,
C.LastName,
C.FullName,
C.DateOfBirth,
G.GenderName,
G.GenderIcon,
C.VerificationCode
我让 sp_BlizFirst 每 12 分钟运行几天,以捕获各种统计数据。
不过我逐渐意识到,除了 I/O 停顿之外,它似乎并没有收集很多与文件相关的性能统计数据。
是否有足够的信息来根据等待统计信息和 I/O 停顿来确定 I/O 是否有问题?我在 Blitz 表中找不到任何关于磁盘平均的提及。读取时间,磁盘平均。写时间,平均。我认为应该考虑磁盘队列长度吗?
任何人都可以就以下内容提供一些反馈吗?我的并行统计数据肯定需要正确查看 (CXPACKET),但我也对我的磁盘 i/o 性能感到好奇。我认为 OLDEDB 等待是由链接服务器和 Idera SQL 诊断管理器每 1 分钟监控一次实例引起的。
从https://www.sqlskills.com/blogs/paul/are-io-latencies-killing-your-performance/我读到以下内容:每个人对什么是好的或坏的 I/O 延迟都有自己的想法,这是我的采取: 优秀:< 1 毫秒 非常好:< 5 毫秒 好:5 – 10 毫秒 差:10 – 20 毫秒 差:20 – 100 毫秒 非常差:100 – 500 毫秒 哇!:> 500 毫秒
如果我按照那个去做,我属于坏类别。
这是我的等待统计数据:
服务器 1
平均读取 I/O 停顿为 23.91
最大读取 I/O 停顿为 1162
平均写入 I/O 停顿为 0.71
最大写入 I/O 停顿为 139
服务器 2
平均读取 I/O 停顿为 26.28
MAX Read I/O Stall 为 428
平均写入 I/O 停顿为 2.60
最大写入 I/O 停顿为 667
这是一个有点尴尬的问题,我不敢相信我已经错过了这么多年。
我有一个包含 401 个堆表的供应商第三方数据库。我最近开始使用 Brent Ozar 的脚本并设置sp_BlitzFirst
为每 15 分钟运行一次以收集等待统计数据等。
它发现的是,每次运行 24 小时后,它都会告诉我修复转发记录。如果我跨 DMV 运行查询并返回一些包含超过 150,000 个转发记录值的表,这可能会让一些读者感到震惊。
我知道解决这个问题是在表中建立一个聚集索引,或者作为运行ALTER TABLE [tablename] REBUILD
.
然而,我无法找到的是这是否会使表脱机,以及在运行此命令之前是否应该注意任何其他问题。
我用的是2008 R2企业版,不知道这样运行会不会断电?
ALTER TABLE [tablename] REBUILD WITH (ONLINE = ON);
有人对这个有经验么?
这是我阅读的后续内容是否有任何理由在维护窗口期间停止事务日志备份?在 sp_BlitzErik 提出的答案中。
我使用 Ola Hallengren 的索引脚本并按照以下指定设置。我每周通过代理工作运行一次。
@Databases nvarchar(max),
@FragmentationLow nvarchar(max) = NULL,
@FragmentationMedium nvarchar(max) = 'INDEX_REORGANIZE,INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationHigh nvarchar(max) = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationLevel1 int = 5,
@FragmentationLevel2 int = 30,
@PageCountLevel int = 500,
我知道作为索引重建的一部分,更新统计信息是自动完成的,但是我针对我的所有数据库设置了以下数据库属性,我认为这些属性应该负责更新统计信息:
Auto Create Statistics = True
Auto Update Statistics = True
Auto Update Statistics Asynchronously = True
这些设置和定期更新统计信息的最佳实践通常是什么?你应该每晚更新统计数据吗?我不确定如何衡量是否应该更新统计信息,这就是我设置这些数据库属性的原因。
我在 sp_BlitzErik 的回答中看到他提到“你仍然想要定期更新统计数据,你可以用这个命令来做到这一点:”
使用以下命令,但定期更新统计信息非常普遍。
EXECUTE dbo.IndexOptimize @Databases = 'USER_DATABASES',
@FragmentationLow = NULL,
@FragmentationMedium = NULL,
@FragmentationHigh = NULL,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y',
@StatisticsSample = NULL,
@LogToTable = 'Y';