服务器 SERVER_A 有一些数据。
服务器SERVER_B将A定义为链接服务器,并定义了一些数据视图。查询是这样的:
CREATE view myview as
select * from
openquery ( SERVER_A, select .... )
Run Code Online (Sandbox Code Playgroud)
服务器 SERVER_C 将 B 定义为链接服务器。
我拥有对 SERVER_C 的完全访问权限,我可以要求对 SERVER_B 进行一些更改,但不能要求对 SERVER_A 进行一些更改。我的所有应用程序都将访问服务器 SERVER_C,并需要来自 SERVER_A 的数据。SERVER_B 上的视图非常复杂,它们会在返回任何内容之前导致超时。
我认为为了提高这些查询的性能,我需要将 SERVER_B 上的视图转换为“索引视图”。要为视图建立索引,我必须创建聚集索引。
问题:
1)我应该在哪里定义聚集索引?它应该在 SERVER_B 上,还是我可以以某种方式在 SERVER_C 上定义它?
2) 即使未使用该视图,在 SERVER_B 上使用索引视图是否会以任何方式影响 SERVER_A 的性能?
我在 Microsoft SQL Server 2016 上有一个数据库,有一个大约一百万行的表,我们称之为书籍。这个查询需要超过一分钟,这是不可接受的:
select * from books wherepublisher_id in (857413, 857317, 857316)
从publisher_id 到publishers 表有一个合适的FK。我显示了 Estimated Execution Plan,它告诉我 100% 的成本都在 book 表的主键上的“Clustered Index Scan (clustered)”中。让我担心的是,它根本不推荐索引。通过查看查询,很明显索引会有所帮助。事实上,当我创建索引时,查询会立即返回结果。我的数据库中有什么东西损坏了,也许是统计数据?或者您认为我应该也不相信我在估计的执行计划中读到的内容?
我有一个 SQL Server 2008R2,我想远程连接到 SQL Server 2012SP1,为此我得到了:
IP: 12.34.56.78
Login: john
Password: pw1
Database: TESTDB
Table: test_table
Run Code Online (Sandbox Code Playgroud)
远程数据库在我的局域网之外,但是两边都配置了防火墙,所以我可以通过直接从我的数据库服务器打开SSMS来查询它。我执行以下操作:
EXEC sp_addlinkedserver '12.34.56.78', 'SQL Server';
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = [12.34.56.78], @locallogin = NULL , @useself = N'False', @rmtuser = 'john', @rmtpassword = 'pw1'
Run Code Online (Sandbox Code Playgroud)
到目前为止,没有错误,我可以在SSMS中看到链接服务器,“测试连接”成功但我无法查询。
select * from [12.34.56.78].TESTDB.test_table
Run Code Online (Sandbox Code Playgroud)
返回此错误:
Msg 208, Level 16, State 1, Line 1
Invalid object name '12.34.56.78.TESTDB.test_table'.
Run Code Online (Sandbox Code Playgroud)
从 Internet 定义链接服务器的正确方法是什么,如果可能,为其分配一个好听的名称(而不是通过 IP 引用它)?我应该使用 SQLNCLI 作为提供程序吗?
我有一个这样的查询:
-- This is inefficient, and may even be wrong if expression is nondeterministic
SELECT TOP 10 team_name,score_points=<big expression>
FROM teams
WHERE <big expression> >= 100
ORDER BY 2 DESC
-- This gives error
SELECT TOP 10 team_name,score_points=<big expression>
FROM teams
WHERE score_points >= 100
ORDER BY 2 DESC
Run Code Online (Sandbox Code Playgroud)
我想要做的很明确:列出得分最高的球队。列出所有得分至少为 100 score_points 的球队,但不超过 10 支球队。
如果我重复这个表达式,它将非常丑陋且效率低下。另外,当我的表达式不确定时,它会给出错误的结果。score_points在WHERE子句中使用名称会出错。有没有一种有效的方法可以让我的表达式的结果既作为查询中的列返回,又用作过滤器?
请不要告诉我有关计算列的信息,我知道它们,但我不能在这里使用它们。
在 StackOverflow 上的一个问题中,我发现了这个查询,它显示了当前数据库中所有表的表和列描述:
SELECT u.name + '.' + t.name AS [table],
td.value AS [table_desc],
c.name AS [column],
cd.value AS [column_desc]
FROM sysobjects t
INNER JOIN sysusers u
ON u.uid = t.uid
LEFT OUTER JOIN sys.extended_properties td
ON td.major_id = t.id
AND td.minor_id = 0
AND td.name = 'MS_Description'
INNER JOIN syscolumns c
ON c.id = t.id
LEFT OUTER JOIN sys.extended_properties cd
ON cd.major_id = c.id
AND cd.minor_id = c.colid
AND cd.name = 'MS_Description'
WHERE t.type = 'u'
ORDER BY t.name, …Run Code Online (Sandbox Code Playgroud) 在我的数据库错误日志(在这个答案中生成)中,我看到以下查询的许多实例(每天数百个):
声明@HkeyLocal nvarchar(18) 声明@ServicesRegPath nvarchar(34) 声明@SqlServiceRegPath 系统名 声明@BrowserServiceRegPath 系统名 声明@MSSqlServerRegPath nvarchar(31) 声明@InstanceNamesRegPath nvarchar(59) 声明@InstanceRegPath 系统名 声明@SetupRegPath 系统名 声明@NpRegPath 系统名 声明@TcpRegPath 系统名 声明@RegPathParams 系统名称 声明@FilestreamRegPath 系统名 选择@HkeyLocal=N'HKEY_LOCAL_MACHINE' -- 基于实例的路径 选择@MSSqlServerRegPath=N'SOFTWARE\Microsoft\MSSQLServer' 选择@InstanceRegPath=@MSSqlServerRegPath + N'\MSSQLServer' 选择@FilestreamRegPath=@InstanceRegPath + N'\Filestream' 选择@SetupRegPath=@MSSqlServerRegPath + N'\Setup' 选择@RegPathParams=@InstanceRegPath+'\Parameters' - 服务 选择@ServicesRegPath=N'SYSTEM\CurrentControlSet\Services' 选择@SqlServiceRegPath=@ServicesRegPath + N'\MSSQLSERVER' 选择@BrowserServiceRegPath=@ServicesRegPath + N'\SQLBrowser' -- InstanceId 设置 选择@InstanceNamesRegPath=N'SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL' - 网络设置 选择@NpRegPath=@InstanceRegPath + N'\SuperSocketNetLib\Np' 选择@TcpRegPath=@InstanceRegPath + N'\SuperSocketNetLib\Tcp' 声明@SmoAuditLevel int exec master.dbo.xp_instance_regread @HkeyLocal, @InstanceRegPath, N'AuditLevel', @SmoAuditLevel OUTPUT 声明 @NumErrorLogs int exec master.dbo.xp_instance_regread @HkeyLocal、@InstanceRegPath、N'NumErrorLogs'、@NumErrorLogs …
我是 Microsoft SQL Server 2008r2 的 DBA。由于试镜,我需要向没有明确 IT 背景的人提供我的数据库的数据结构。我猜他们会喜欢传统的格式,表格是矩形,字段列在里面,它们之间的箭头代表外键。这是 Microsoft 开箱即用的东西吗?
我在我的数据库中记录了最慢的查询,其中一个让我感到惊讶,在列表中显示了很多次,并且执行通常需要很多秒。
UPDATE books SET last_read='2018-12-31 11:23:45' WHERE book_id='15'
Run Code Online (Sandbox Code Playgroud)
book_id 是 int 身份 PK(集群),last_read 是日期时间。查询是用单引号中的 15 编写的,因此需要转换,但我无法想象这是一个大问题,因为每个查询只进行一次转换。表上有 6 个索引,但列 last_read 未涉及或包含在其中任何一个中。PK 在 book_id 上,没什么特别的。
估计的执行计划告诉我:
UPDATE: 0%
Clustered Index Update (on the PK constraint): 100%
Run Code Online (Sandbox Code Playgroud)
我不希望查询更新任何索引,因为 last_read 没有以任何方式编入索引,并且 book_id 没有更改。
我错过了什么?
在我正在处理的数据库中,有一个名为 的表,persons大约有一百万行,并且来自其他表(有些有数百万行)的 60 个 FK (FK) 约束指向它。
如果我从 中删除一行persons,则需要很多分钟,这不会是问题,但它也会使表保持锁定,从而阻止数据库的所有进程。过去,这曾导致用户报告系统宕机。
当然,如果我为所有的FK添加支持索引的话,情况会大大改善(目前60张表中只有20张有)。但是这些FK很多都是针对诸如 之类的列modified_by,因此所有索引都没有其他目的,并且会在日常操作中降低系统的性能,只有在特殊情况下才能获得改进。
在运行 DELETE 之前,我已经确保所有引用行都已被删除或更新。我手动执行此操作,因为我强烈反对使用 CASCADE。
我没有考虑软删除,因为否则我将不得不更改读取表persons以跳过已删除行的所有软件。
有没有办法(可能是暂时的)更改表的锁定机制persons,以便即使 DELETE 需要一个小时,也不会影响并发进程?
禁用 FK 可能是一种可能。风险在于,当我删除该行时,其他人会造成不一致,然后我无法重新启用 FK。
要删除的行:通常一次删除一行。手动操作或计划操作。
有趣的一点:我没有立即检查执行计划,但显然,除了引用表的 PK 上的 7 例“聚集索引扫描(Clustered)”之外,几乎所有操作的成本都是 0%;其中一种费用为 57%,另一种费用为 1% 至 16%。我仍然不明白为什么它应该扫描聚集索引。
我的数据库中最重要的表大约有 300,000 条记录,而且还在不断增加。20 多张桌子都有 FK。它的主键是一个数字,但由于历史原因被定义为 nvarchar(6),这显然是低效的(而且丑陋)。记录有时会从记录中删除,因此主键接近999,999,我必须更改它。身份字段将是显而易见的选择。具有由触发器或软件产生的增量的 int 键或类似键将是一种替代方法。这是可行的,因为记录总是一次插入一个。int 键会为复杂查询提供更好的性能吗?