标签: sql-server-2014

SQL Server 中的海量数据和性能

我编写了一个带有 SQL Server 后端的应用程序,用于收集和存储大量记录。我已经计算出,在高峰期,平均记录量大约为每天 3-40 亿条(运行 20 小时)。

我最初的解决方案(在我完成数据的实际计算之前)是让我的应用程序将记录插入到我的客户查询的同一个表中。显然,这会很快崩溃并烧毁,因为不可能查询插入了这么多记录的表。

我的第二个解决方案是使用 2 个数据库,一个用于应用程序接收的数据,另一个用于客户端就绪数据。

我的应用程序将接收数据,将其分成大约 10 万条记录的批次,然后批量插入到临时表中。在大约 100k 条记录之后,应用程序将使用与之前相同的架构即时创建另一个临时表,并开始插入到该表中。它将在具有 10 万条记录的作业表中创建一条记录,并且 SQL Server 端的存储过程会将数据从临时表移动到客户端就绪的生产表,然后删除我的应用程序创建的表临时表。

除了具有作业表的临时数据库外,两个数据库都具有相同的 5 个表集,具有相同的架构。临时数据库在大量记录将驻留的表上没有完整性约束、键、索引等。如下所示,表名是SignalValues_staging. 目标是让我的应用程序尽快将数据发送到 SQL Server。动态创建表以便轻松迁移的工作流程非常有效。

以下是我的临时数据库中的 5 个相关表,以及我的工作表:

临时表 我编写的存储过程处理从所有临时表中移动数据并将其插入到生产中。下面是我的存储过程的一部分,它从临时表插入到生产中:

-- Signalvalues jobs table.
SELECT *
      ,ROW_NUMBER() OVER (ORDER BY JobId) AS 'RowIndex'
INTO #JobsToProcess
FROM 
(
    SELECT JobId 
           ,ProcessingComplete  
           ,SignalValueStagingTableName AS 'TableName'
           ,(DATEDIFF(SECOND, (SELECT last_user_update
                              FROM sys.dm_db_index_usage_stats
                              WHERE database_id = DB_ID(DB_NAME())
                                AND OBJECT_ID = OBJECT_ID(SignalValueStagingTableName))
                     ,GETUTCDATE())) SecondsSinceLastUpdate
    FROM SignalValueJobs
) cte
WHERE cte.ProcessingComplete = 1 …
Run Code Online (Sandbox Code Playgroud)

performance sql-server sql-server-2014 query-performance

20
推荐指数
2
解决办法
2万
查看次数

使用 GUI 还原数据库 - 要还原的文件错误

我只是在摆弄 SSMS 图形界面并研究“恢复”任务的选项。

我注意到的一件事是,当我单击“生成脚本”时,查询的第一行是:

 RESTORE DATABASE [MyDatabase] FROM  DISK = N'Server_Patch\Database_name_LOGSHIPPING.BKP' WITH  FILE = 1,  NORECOVERY,  NOUNLOAD,  STATS = 5 ( and a lot of log backups for point in time )
Run Code Online (Sandbox Code Playgroud)

好的,没问题,但是,我每天都在备份这个数据库。这Database_name_LOGSHIPPING.BKP是我一个月前为日志传送制作的文件的名称。

为什么当我尝试使用 SSMS 图形界面恢复备份时,它指向这个备份文件?我什至没有这个文件了。


通过 MSSQLTIPS 的这个查询,我可以看到这个数据库的所有备份:

SELECT 
CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS Server, 
msdb.dbo.backupset.database_name, 
msdb.dbo.backupset.backup_start_date, 
msdb.dbo.backupset.backup_finish_date, 
msdb.dbo.backupset.expiration_date, 
CASE msdb..backupset.type 
WHEN 'D' THEN 'Database' 
WHEN 'L' THEN 'Log' 
END AS backup_type, 
msdb.dbo.backupset.backup_size, 
msdb.dbo.backupmediafamily.logical_device_name, 
msdb.dbo.backupmediafamily.physical_device_name, 
msdb.dbo.backupset.name AS backupset_name, 
msdb.dbo.backupset.description 
FROM msdb.dbo.backupmediafamily 
INNER JOIN msdb.dbo.backupset ON msdb.dbo.backupmediafamily.media_set_id = msdb.dbo.backupset.media_set_id 
WHERE …
Run Code Online (Sandbox Code Playgroud)

sql-server restore sql-server-2014

20
推荐指数
1
解决办法
1886
查看次数

使用 SQL Server 中另一个表中的值更新表

我的数据库中有 2 个表。

表格1

-------------------------------------------------------------------------
| name | family | phone | email | gender | phone2 | address | birthdate |
-------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

表#2

-----------------------------------------
| gender | address | phone | birthdate |
-----------------------------------------
Run Code Online (Sandbox Code Playgroud)

在表#1的列地址PHONE2是空的和列性别生日的值是相同的表#2。

当每行的性别出生日期相同时,如何从表 #2 中读取数据并使用表 #2 addressphone列中的值更新表 #1 中的addressphone2

例如:这是表 #1 中的一些数据

-------------------------------------------------------------------------
| name | family | phone | email | gender | phone2 | address …
Run Code Online (Sandbox Code Playgroud)

join sql-server t-sql update sql-server-2014

20
推荐指数
1
解决办法
22万
查看次数

为什么 Concatenation 运算符估计的行数少于其输入?

在下面的查询计划片段中,很明显Concatenation运算符的行估计应该是~4.3 billion rows,或者它的两个输入的行估计的总和。

但是,~238 million rows会产生的估计值,从而导致将数百 GB 数据溢出到 tempdb的次优Sort/Stream Aggregate策略。在这种情况下,逻辑上一致的估计会产生Hash Aggregate,消除溢出并显着提高查询性能。

这是 SQL Server 2014 中的错误吗?是否存在任何有效情况下低于输入值的估计是合理的?可能有哪些解决方法?

在此处输入图片说明

这是完整的查询计划(匿名)。我没有系统管理员访问此服务器的权限以提供来自QUERYTRACEON 2363或类似跟踪标志的输出,但如果它们有帮助,我可以从管理员那里获取这些输出。

数据库的兼容性级别为 120,因此使用新的 SQL Server 2014 Cardinality Estimator。

每次加载数据时都会手动更新统计信息。鉴于数据量,我们目前使用默认采样率。较高的采样率(或FULLSCAN)可能会产生影响。

performance sql-server concat sql-server-2014 cardinality-estimates query-performance

20
推荐指数
2
解决办法
783
查看次数

在窗口函数中使用 DISTINCT 和 OVER

我正在尝试将查询从 Oracle 迁移到 SQL Server 2014。

这是我在 Oracle 中运行良好的查询:

select
count(distinct A) over (partition by B) / count(*) over() as A_B
from MyTable 
Run Code Online (Sandbox Code Playgroud)

这是我尝试在 SQL Server 2014 中运行此查询后遇到的错误。

Use of DISTINCT is not allowed with the OVER clause
Run Code Online (Sandbox Code Playgroud)

有谁知道是什么问题?在 SQL Server 中可以进行这种查询吗?请指教。

sql-server window-functions sql-server-2014

19
推荐指数
4
解决办法
5万
查看次数

无法在计算列上创建筛选索引

在我之前的一个问题中,在向表中添加新的计算列时禁用锁升级是个好主意吗?,我正在创建一个计算列:

ALTER TABLE dbo.tblBGiftVoucherItem
ADD isUsGift AS CAST
(
    ISNULL(
        CASE WHEN sintMarketID = 2 
            AND strType = 'CARD'
            AND strTier1 LIKE 'GG%' 
        THEN 1 
        ELSE 0 
        END
    , 0) 
    AS BIT
) PERSISTED;
Run Code Online (Sandbox Code Playgroud)

计算列是PERSISTED,并且根据计算列定义(Transact-SQL)

坚持

指定数据库引擎将计算值物理存储在表中,并在计算列所依赖的任何其他列更新时更新值。将计算列标记为 PERSISTED 允许在确定性但不精确的计算列上创建索引。有关更多信息,请参阅计算列上的索引。任何用作分区表的分区列的计算列都必须显式标记为 PERSISTED。当指定 PERSISTED 时,computed_column_expression 必须是确定性的。

但是当我尝试在我的列上创建索引时,我收到以下错误:

CREATE INDEX FIX_tblBGiftVoucherItem_incl
ON dbo.tblBGiftVoucherItem (strItemNo) 
INCLUDE (strTier3)
WHERE isUsGift = 1;
Run Code Online (Sandbox Code Playgroud)

无法在表 'dbo.tblBGiftVoucherItem' 上创建过滤索引 'FIX_tblBGiftVoucherItem_incl',因为过滤器表达式中的列 'isUsGift' 是计算列。重写过滤器表达式,使其不包含此列。

如何在计算列上创建过滤索引?

或者

有替代的解决方案吗?

index sql-server filtered-index sql-server-2014 computed-column

19
推荐指数
3
解决办法
4271
查看次数

强迫流不同

我有一张这样的表:

CREATE TABLE Updates
(
    UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    ObjectId INT NOT NULL
)
Run Code Online (Sandbox Code Playgroud)

本质上是跟踪 ID 增加的对象的更新。

该表的使用者将选择一个由 100 个不同对象 ID 组成的块,按UpdateId特定的UpdateId. 本质上,跟踪它停止的位置,然后查询任何更新。

我发现这是一个有趣的优化问题,因为我只能通过编写由于索引而碰巧做我想要的查询来生成最大优化的查询计划,但不保证我想要什么:

SELECT DISTINCT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
Run Code Online (Sandbox Code Playgroud)

@fromUpdateId存储过程参数在哪里。

有以下计划:

SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek
Run Code Online (Sandbox Code Playgroud)

由于UpdateId正在使用索引上的搜索,结果已经很好,并且按照我想要的从最低到最高的更新 ID 排序。这会生成一个流程不同的计划,这就是我想要的。但是排序显然不能保证行为,所以我不想使用它。

这个技巧也会产生相同的查询计划(尽管有一个冗余的 TOP):

WITH ids AS
(
    SELECT ObjectId
    FROM Updates …
Run Code Online (Sandbox Code Playgroud)

performance sql-server optimization sql-server-2014 query-performance

19
推荐指数
3
解决办法
797
查看次数

内存优化表 - 它们真的很难维护吗?

我正在研究从 MS SQL 2012 升级到 2014 的好处。SQL 2014 的一大卖点是内存优化表,这显然使查询速度超快。

我发现内存优化表有一些限制,例如:

  • 没有(max)大小的字段
  • 每行最大 ~1KB
  • timestamp字段
  • 没有计算列
  • 没有UNIQUE限制

这些都属于麻烦事,但如果我真的想解决这些问题以获得性能优势,我可以制定计划。

真正的问题是您无法运行ALTER TABLE语句,并且每次向索引列表添加字段时都必须经历这些繁琐INCLUDE的过程。此外,您似乎必须将用户拒之门外,才能对实时数据库上的 MO 表进行任何架构更改。

我觉得这简直太离谱了,以至于我实际上无法相信 Microsoft 会在此功能上投入如此多的开发资金,却让其维护起来如此不切实际。这使我得出结论,我一定是拿错了棍子的一端;我一定误解了内存优化表的某些内容,这让我相信维护它们比实际困难得多。

那么,我误解了什么?你用过MO表吗?是否有某种秘密开关或过程使它们易于使用和维护?

index sql-server alter-table sql-server-2014 memory-optimized-tables

18
推荐指数
2
解决办法
4402
查看次数

错误消息 - 查看服务器状态权限被拒绝 - 使用 SQL Server 2012 Management Studio 连接到 SQL Server 2014 时

右键单击表格并选择“选择前 1000 行”时,出现此错误:

在此处输入图片说明

除了明显升级到 SQL Server 2014 之外,还有其他解决方法吗?

sql-server ssms sql-server-2012 connectivity sql-server-2014

18
推荐指数
2
解决办法
5万
查看次数

SQL Server UniqueIdentifier / GUID 内部表示

我的一位同事给我发了一个有趣的问题,我无法完全解释。

他运行了一些代码(包括在下面)并从中得到了一些意想不到的结果。

本质上,当将 a UniqueIdentifierGuid从这里开始我将称之为)转换为 a binary(or varbinary) 类型时,结果的前半部分的顺序是倒序的,但后半部分不是。

我的第一个想法是系统的字节序是原因,并且Guid保留了显示,但binary不能保证形式。

显然这是一个实现细节,但我想知道是否有一个很好的解释。

代码:

declare @guid uniqueidentifier = '8A737954-CBEC-40CE-A534-2AFFB5A0E207';
declare @binary binary(16) = (select convert(binary(16), @guid));
select @guid as [GUID], @binary as [Binary];
Run Code Online (Sandbox Code Playgroud)

结果:

GUID                                 Binary
8A737954-CBEC-40CE-A534-2AFFB5A0E207 0x5479738AECCBCE40A5342AFFB5A0E207
Run Code Online (Sandbox Code Playgroud)

如您所见,每个部分的前半部分Guid(一直到40CE)是向后存储的。也就是说,the的第一部分是向后的,然后是第二部分,然后是第三部分,但是这些部分的顺序是保留的。之后,最后两个部分按照它们在.GuidGuid

谁能解释一下?(下面包含一个更大的测试集。)

代码:

declare @guid_to_binary table
(
    [id] int identity(1,1),
    [guid] uniqueidentifier,
    [binary_conversion] binary(16)
);
declare @i int = 1;
while @i <= 100
begin
    insert into …
Run Code Online (Sandbox Code Playgroud)

sql-server uniqueidentifier sql-server-2014 uuid

18
推荐指数
1
解决办法
4086
查看次数