我可以使用什么查询来确定存储过程在 SQL Server 2012 中每次执行时是否都会重新编译?我怀疑我们的某些存储过程可能会被重新编译,但我不确定如何检查。谢谢!
lifeisajourney's questions
我们在 SQL Server 2019 上有一个数据库,兼容性设置为 110(SQL Server 2012)。我们有一个经常重新编译的存储过程,我注意到我们正在使用许多临时表。我们创建一个临时表,插入数据,然后在其上添加索引以供进一步查询。我怀疑这可能会导致重新编译。临时表会触发重新编译吗?如果会,在什么条件下?谢谢!
我一直试图通过链接服务器从我们的仓库服务器访问我们的报告服务器(辅助副本)上的表。直到上周一切都运行顺利,但现在它抛出了“无法在系统目录中找到统计信息”错误。
经过一番研究,我似乎需要删除并重新创建导致此问题的统计数据。但是,我犹豫是否在我们的实时生产服务器上这样做。我仍然不太清楚到底是什么导致了这个问题。
有人能解释一下可能发生了什么吗?是否有解决方法,不需要删除并重新创建统计数据?我非常感谢您的帮助和时间。谢谢!
我有下表
Create table #products
(
productId int,
regionId int,
date datetime,
active bit
)
insert into #products values
(1,20,'10/10/2020',1),(1,20,'12/10/2022',0),(1,20,'5/8/2023',1),
(2,20,'11/11/2020',0),(2,20,'12/12/2022',1),(2,20,'5/8/2023',0),
(3,20,'10/10/2020',1),(3,20,'12/10/2022',0),(3,20,'5/8/2023',1)
我试图找出哪些产品在 2023 年 3 月 1 日至 2023 年 3 月 30 日期间处于活动状态。查看提供的数据,在此期间只有产品 ID 2 处于活动状态。如何编写 SQL 查询来准确检索此信息?我尝试了一些查询,但没有得到我期望的结果。在此先感谢您的时间!
我有以下查询,我正在查找该列不等于 1 的任何行istrue
。但结果只包含 0 的记录,忽略 null 的记录。虽然我知道使用(istrue != 1 or istrue is null)会产生预期的结果,但我很好奇导致 SQL Server 排除 null 值的底层机制。您能否提供对此行为的见解?谢谢!
create table #test
(
id int,
val varchar(100),
istrue bit
)
insert into #test values
(1, 'test-1', 1),
(2, 'test-2', 0),
(3, 'test-3', 1),
(4, 'test-4', 0),
(5, 'test-5', null),
(6, 'test-6', null)
select * from #test
where istrue != 1
drop table if exists #test
我有以下表格
-- Create the #product table
CREATE TABLE #product
(
id UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(),
name VARCHAR(100),
createdDate DATE
);
-- Create the #tmpproducts table
CREATE TABLE #tmpProducts
(
rownum INT PRIMARY KEY IDENTITY(1,1),
name VARCHAR(100),
createdDate DATE
);
-- Insert data into #tmpSignings
INSERT INTO #tmpProducts (name, createdDate)
VALUES
('John Doe', '2023-11-22'),
('Jane Smith', '2023-11-23'),
('Alice Johnson', '2023-11-24'),
('Bob Williams', '2023-11-25'),
('Eva Brown', '2023-11-26'),
('Michael Davis', '2023-11-27'),
('Sophia Miller', '2023-11-28'),
('William Wilson', '2023-11-29'),
('Olivia Jones', '2023-11-30'),
('Daniel White', '2023-12-01');
我在 #tmpProducts 中有 10 行,我的目标是将这些行插入到 #product 表中。对于成功插入到产品表中的每一行,我需要将新生成的 ID 关联回 #tmpProducts 表中相应的 rownum。我怎样才能做到这一点?任何帮助是极大的赞赏。谢谢你!
预期输出:
我有两个表,#customer 和 #abbr。#customer 表由两列组成:“id”和“name”,而 #abbr 表包含缩写词及其相应的完整形式的条目。我的目标是将客户名称中的所有缩写替换为其各自的完整形式。例如,如果客户名称是“Object ME CT”,我希望结果是“Object Medical Control”。但是,根据我当前的查询,它会生成两行:“对象 ME 控制”和“对象医疗 CT”。我的目标是每个“id”占一行,其中所有缩写都替换为 #abbr 表中的完整形式。我怎样才能实现这个目标?谢谢你!
create table #customer
(
id int identity(1,1)
,cname varchar(100)
)
create table #abbr
(
abbr varchar(100),
fname varchar(100)
)
insert into #customer values('Assign ME CT'),('Assign ME'),('Assign CT')
insert into #abbr values ('ME','Medical'),('CT','Control'),('MMT','Metro')
select *, REPLACE(c.cname, a.abbr,a.fname)
from #customer c
join #abbr a
on c.cname like '%'+a.abbr+'%'
where id = 1
我有两个表 - 订单和产品。每个订单可以有 0 个或多个产品。
--drop table orders
--drop table products
CREATE TABLE Orders (
OrderId INT PRIMARY KEY,
OrderDate DATE,
CustomerName VARCHAR(50)
);
CREATE TABLE Products (
ProductId INT PRIMARY KEY,
ProductName VARCHAR(50),
Price DECIMAL(10, 2),
OrderId INT,
FOREIGN KEY (OrderId) REFERENCES Orders(OrderId)
);
INSERT INTO Orders (OrderId, OrderDate, CustomerName)
VALUES (1, '2023-01-01', 'John Doe'),
(2, '2023-01-02', 'Jane Smith'),
(3, '2023-01-03', 'Michael Johnson'),
(4, '2023-01-04', 'Emily Davis'),
(5, '2023-01-05', 'Robert Wilson'),
(6, '2023-01-06', 'Olivia Thompson'),
(7, '2023-01-07', 'William Anderson'),
(8, '2023-01-08', 'Sophia Martinez'),
(9, '2023-01-09', 'James Hernandez'),
(10, '2023-01-10', 'Ava Lee'),
(11, '2023-01-11', 'Benjamin Walker'),
(12, '2023-01-12', 'Mia Lewis'),
(13, '2023-01-13', 'Ethan Hall'),
(14, '2023-01-14', 'Charlotte White'),
(15, '2023-01-15', 'Alexander King'),
(16, '2023-01-16', 'Amelia Scott'),
(17, '2023-01-17', 'Daniel Green'),
(18, '2023-01-18', 'Harper Adams'),
(19, '2023-01-19', 'Matthew Clark'),
(20, '2023-01-20', 'Luna Rodriguez'),
(21, '2023-01-21', 'Henry Carter'),
(22, '2023-01-22', 'Lily Hill'),
(23, '2023-01-23', 'Sebastian Turner'),
(24, '2023-01-24', 'Avery Ward'),
(25, '2023-01-25', 'Scarlett Foster'),
(26, '2023-01-26', 'Joseph Diaz'),
(27, '2023-01-27', 'Victoria Morris'),
(28, '2023-01-28', 'David Sullivan'),
(29, '2023-01-29', 'Penelope Price'),
(30, '2023-01-30', 'Jackson Brooks');
INSERT INTO Products (ProductId, ProductName, Price, OrderId)
VALUES
-- Products for OrderId 1
(1, 'Product A', 10.99, 1),
(2, 'Product B', 19.99, 1),
-- Products for OrderId 2
(3, 'Product C', 5.99, 2),
-- Products for OrderId 3
(4, 'Product D', 7.50, 3),
(5, 'Product E', 14.99, 3),
(6, 'Product F', 8.99, 3),
-- Products for OrderId 4
(7, 'Product G', 12.99, 4),
(8, 'Product H', 9.99, 4),
(9, 'Product I', 6.49, 4),
-- Products for OrderId 5
(10, 'Product J', 18.50, 5),
(11, 'Product K', 11.99, 5),
-- Products for OrderId 6
(12, 'Product L', 7.99, 6),
(13, 'Product M', 13.99, 6),
-- Products for OrderId 7
(14, 'Product N', 9.99, 7),
-- Products for OrderId 8
(15, 'Product O', 16.99, 8),
(16, 'Product P', 14.50, 8),
-- Products for OrderId 9
(17, 'Product Q', 8.99, 9),
(18, 'Product R', 6.99, 9),
-- Products for OrderId 10
(19, 'Product S', 12.99, 10),
-- Products for OrderId 11
(20, 'Product T', 7.50, 11),
-- Products for OrderId 12
(21, 'Product U', 9.99, 12),
(22, 'Product V', 11.99, 12),
-- Products for OrderId 13
(23, 'Product W', 15.99, 13),
(24, 'Product X', 8.50, 13),
-- Products for OrderId 14
(25, 'Product Y', 9.99, 14),
-- Products for OrderId 15
(26, 'Product Z', 12.99, 15),
(27, 'Product AA', 7.99, 15),
(28, 'Product BB', 14.99, 15),
-- Products for OrderId 16
(29, 'Product CC', 11.50, 16),
(30, 'Product DD', 9.99, 16);
要求:编写一个查询,根据查询中传递的过滤器
过滤表customerName
中的列Orders
或表ProductName
中的列,并按其排序并获取请求的订单数。这是我写的查询,但它没有完成我正在寻找的内容:Products
OrderDate
declare @filter varchar(100) = 't'
declare @skiprows int = 5
declare @limitrows int = 5
select *
from dbo.orders o
left join dbo.products p
on o.orderId = p.orderId
where (customerName like '%'+@filter+'%'
or productName like '%'+@filter+'%')
order by orderdate desc
offset @skiprows rows
fetch next @limitrows rows only
参数@limitrows
和@skiprows
用于确定所需的结果集。但是,在给定的查询中,跳过前 5 行并返回接下来的 5 行并不能提供预期的结果。目标是跳过前 5 个不同的订单 ID,然后选择接下来的 5 个不同的订单 ID。随后,结果集应与 Products 表连接以检索所有相应的产品。需要注意的是,由于每个订单可以有多个产品,因此最终结果集可能包含超过 5 行。如果有人可以提供如何实现这一目标的指导,我们将不胜感激。谢谢你!
我有下表和数据:
CREATE TABLE myTable (
ID INT IDENTITY(1,1) PRIMARY KEY,
Column1 VARCHAR(50),
Column2 VARCHAR(50),
Column3 VARCHAR(50),
Column4 VARCHAR(50),
Column5 VARCHAR(50),
Column6 VARCHAR(50),
Column7 VARCHAR(50),
Column8 VARCHAR(50),
Column9 VARCHAR(50),
Column10 VARCHAR(50)
)
DECLARE @i INT = 1
DECLARE @j INT = 1
DECLARE @distinct_value_count INT = 20
DECLARE @distinct_value_count_with_more_rows INT = 3
DECLARE @rows_per_distinct_value INT = (20000 - (@distinct_value_count_with_more_rows * 2000)) / (@distinct_value_count - @distinct_value_count_with_more_rows)
WHILE @i <= @distinct_value_count
BEGIN
DECLARE @current_rows_per_value INT = @rows_per_distinct_value
IF @i <= @distinct_value_count_with_more_rows
BEGIN
SET @current_rows_per_value = @rows_per_distinct_value + 2000
END
SET @j = 1
WHILE @j <= @current_rows_per_value
BEGIN
INSERT INTO myTable (Column1, Column2, Column3, Column4, Column5, Column6, Column7, Column8, Column9, Column10)
VALUES ('Value' + CAST(@i AS VARCHAR(2)),
'Value' + CAST(@j AS VARCHAR(5)),
'Value' + CAST(@j + 1 AS VARCHAR(5)),
'Value' + CAST(@j + 2 AS VARCHAR(5)),
'Value' + CAST(@j + 3 AS VARCHAR(5)),
'Value' + CAST(@j + 4 AS VARCHAR(5)),
'Value' + CAST(@j + 5 AS VARCHAR(5)),
'Value' + CAST(@j + 6 AS VARCHAR(5)),
'Value' + CAST(@j + 7 AS VARCHAR(5)),
'Value' + CAST(@j + 8 AS VARCHAR(5)))
SET @j = @j + 1
END
SET @i = @i + 1
END
Alter Table dbo.myTable
Add Column11 varchar(50), Column12 varchar(50)
Alter Table dbo.myTable
Add dateModified datetime
Update dbo.myTable
set Column11 = Column1
,Column12 = Column1
Update Top (10) dbo.myTable
Set Column11 = 'Value7'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column12 = 'Value7'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column11 = 'Value6'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column12 = 'Value6'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column11 = 'Value5'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column12 = 'Value5'
Where Column1 = 'Value1'
Update dbo.myTable
set dateModified = getdate() + ID
CREATE NONCLUSTERED INDEX [Idx_col] ON [dbo].[myTable]
(
[Column1] ASC,
[Column11] ASC,
[Column12] ASC,
[dateModified] ASC
)
INCLUDE([Column5],[Column6])
我必须根据几列进行过滤并返回表中的所有列。为此,我有一个索引涵盖需要过滤的列。我将查询分为两部分:
获取所有满足过滤器的主键行并将它们存储在临时表中。此查询使用非聚集索引。
将此临时表连接回主键列上的主表,以便聚集索引用于获取所有列。
但是,当我尝试这样做时,我遇到了一个问题。在第一个场景中,我将所有过滤的行放入一个临时表中,然后当我将它连接回主表时,它正在执行聚簇索引扫描。在第二种情况下,我只将前 50 行放入临时表,当我将其连接到主表时,它正在执行聚集索引查找。我很困惑为什么会这样。在这两种情况下,临时表上都没有索引。如果有人能帮助我了解发生了什么,我将不胜感激。谢谢你!
场景 1:
SELECT id
INTO #tmpId
FROM myTable
WHERE Column1= 'Value1'
AND Column11 In( 'Value1','Value5','Value6', 'Value7')
And Column12 In ('Value1','Value6')
And dateModified > dateAdd(day,-5, getdate())
SELECT *
FROM myTable m
JOIN #tmpId t
ON m.id = t.id
drop table if exists #tmpId
执行计划场景 1: https://www.brentozar.com/pastetheplan/? id=rkDAD-aLh
场景 2:
SELECT id
INTO #tmpId
FROM myTable
WHERE Column1= 'Value1'
AND Column11 In( 'Value1','Value5','Value6', 'Value7')
And Column12 In ('Value1','Value6')
And dateModified > dateAdd(day,-5, getdate())
Order by dateModified desc offset 0 rows fetch next 50 rows only
SELECT *
FROM myTable m
JOIN #tmpId t
ON m.id = t.id
drop table if exists #tmpId
场景 2 执行计划: https://www.brentozar.com/pastetheplan/? id=rJVbuWaLh
我有下表和数据。我有两个索引:一个只包含 where 子句中的几列,另一个包含 where 子句中的所有列。
在查询中使用不同的索引时,我对观察到的行为感到困惑。具体来说,当我使用第一个索引时,它只包含 where 子句中的几列,我注意到逻辑读取次数很少,但读取的行数却很多。相反,当我使用包含 where 子句中所有列的索引时,逻辑读取数增加而读取的行数减少。在第一种情况下,存在残留谓词,导致引擎扫描从查找操作检索到的所有行。然而,在第二种情况下,引擎直接寻找必要的值。鉴于此,我预计第二种情况下的逻辑读取次数会更少。我将不胜感激任何关于为什么会发生这种情况的见解。谢谢你!
CREATE TABLE myTable (
ID INT IDENTITY(1,1) PRIMARY KEY,
Column1 VARCHAR(50),
Column2 VARCHAR(50),
Column3 VARCHAR(50),
Column4 VARCHAR(50),
Column5 VARCHAR(50),
Column6 VARCHAR(50),
Column7 VARCHAR(50),
Column8 VARCHAR(50),
Column9 VARCHAR(50),
Column10 VARCHAR(50)
)
DECLARE @i INT = 1
DECLARE @j INT = 1
DECLARE @distinct_value_count INT = 20
DECLARE @distinct_value_count_with_more_rows INT = 3
DECLARE @rows_per_distinct_value INT = (20000 - (@distinct_value_count_with_more_rows * 2000)) / (@distinct_value_count - @distinct_value_count_with_more_rows)
WHILE @i <= @distinct_value_count
BEGIN
DECLARE @current_rows_per_value INT = @rows_per_distinct_value
IF @i <= @distinct_value_count_with_more_rows
BEGIN
SET @current_rows_per_value = @rows_per_distinct_value + 2000
END
SET @j = 1
WHILE @j <= @current_rows_per_value
BEGIN
INSERT INTO myTable (Column1, Column2, Column3, Column4, Column5, Column6, Column7, Column8, Column9, Column10)
VALUES ('Value' + CAST(@i AS VARCHAR(2)),
'Value' + CAST(@j AS VARCHAR(5)),
'Value' + CAST(@j + 1 AS VARCHAR(5)),
'Value' + CAST(@j + 2 AS VARCHAR(5)),
'Value' + CAST(@j + 3 AS VARCHAR(5)),
'Value' + CAST(@j + 4 AS VARCHAR(5)),
'Value' + CAST(@j + 5 AS VARCHAR(5)),
'Value' + CAST(@j + 6 AS VARCHAR(5)),
'Value' + CAST(@j + 7 AS VARCHAR(5)),
'Value' + CAST(@j + 8 AS VARCHAR(5)))
SET @j = @j + 1
END
SET @i = @i + 1
END
Alter Table dbo.myTable
Add Column11 varchar(50), Column12 varchar(50)
Alter Table dbo.myTable
Add dateModified datetime
Update dbo.myTable
set Column11 = Column1
,Column12 = Column1
Update Top (10) dbo.myTable
Set Column11 = 'Value7'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column12 = 'Value7'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column11 = 'Value6'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column12 = 'Value6'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column11 = 'Value5'
Where Column1 = 'Value1'
Update Top (10) dbo.myTable
Set Column12 = 'Value5'
Where Column1 = 'Value1'
Update dbo.myTable
set dateModified = getdate() + ID
案例 1:逻辑读取数低但行数高
Create NonClustered Index Idx_col1
On myTable(Column1, Column11)
Include (Column5, Column6,Column12, dateModified)
set Statistics io on
SELECT Column1
, Column11
, Column5
, Column6
, Column12
FROM myTable
WHERE Column1= 'Value1'
AND Column11 In( 'Value1','Value5','Value6', 'Value7')
And Column12 In ('Value1','Value6')
And dateModified > dateAdd(day,-5, getdate())
执行计划:https://www.brentozar.com/pastetheplan/? id=Sywz516Hh
IO统计:
(2803 rows affected)
Table 'myTable'. Scan count 4, logical reads 34, physical reads 1, page server reads 0, read-ahead reads 23, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
(1 row affected)
案例 2:逻辑读取高但读取的行数低
Create NonClustered Index Idx_col2 on myTable(Column1, Column11,Column12, dateModified)
Include (Column5, Column6)
set Statistics io on
SELECT Column1
, Column11
, Column5
, Column6
, Column12
FROM myTable
WHERE Column1= 'Value1'
AND Column11 In( 'Value1','Value5','Value6', 'Value7')
And Column12 In ('Value1','Value6')
And dateModified > dateAdd(day,-5, getdate())
执行计划:https://www.brentozar.com/pastetheplan/? id=HyWbi1aSh
IO统计:
(2803 rows affected)
Table 'myTable'. Scan count 8, logical reads 47, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
我有一个表,其中有一列包含 JSON 对象。在这些对象中,我需要找到type
值为 3 的键。找到后,我需要price
在嵌套的 JSON 对象中用新值 99更新键data
。其他类型的价格应保持不变。如有任何帮助,我将不胜感激。谢谢你!
-- Create the new table
CREATE TABLE ModifiedTable (
accountIdentifier UNIQUEIDENTIFIER,
settings NVARCHAR(MAX)
);
-- Insert the modified values
INSERT INTO ModifiedTable (accountIdentifier, settings)
Values (
'8E9B45D7-8AEC-EA11-8B03-000D3A12F259',
'[{"type":3,"data":{"required":false,"price":0.5,"display_name":false}},{"type":5,"data":{"required":true,"scaling_factor":2.5, "price":1,"date_format":"yyyy-MM-dd"}}]'
),
(
'C03D12B1-8BEC-EA11-8B03-000D3A12F259',
'[{"type":7,"data":{"required":true,"scaling_factor":1.75,"tooltip":"Sample tooltip", "price":1}},{"type":4,"data":{"required":false,"scaling_factor":1.2,"char_limit":50,"multi_line":true}},{"type":3,"data":{"required":false,"price":0.7,"display_name":false}}]'
);
-- Select from the modified table
SELECT * FROM ModifiedTable;
--drop table ModifiedTable
我有一个存储过程,它为不同的参数生成略有不同的计划。我希望它使用第一次运行时生成的相同计划。
CREATE TABLE myTable (
ID INT IDENTITY(1,1) PRIMARY KEY,
Column1 VARCHAR(50),
Column2 VARCHAR(50),
Column3 VARCHAR(50),
Column4 VARCHAR(50),
Column5 VARCHAR(50),
Column6 VARCHAR(50),
Column7 VARCHAR(50),
Column8 VARCHAR(50),
Column9 VARCHAR(50),
Column10 VARCHAR(50)
)
DECLARE @i INT = 1
DECLARE @j INT = 1
DECLARE @distinct_value_count INT = 20
DECLARE @distinct_value_count_with_more_rows INT = 3
DECLARE @rows_per_distinct_value INT = (20000 - (@distinct_value_count_with_more_rows * 2000)) / (@distinct_value_count - @distinct_value_count_with_more_rows)
WHILE @i <= @distinct_value_count
BEGIN
DECLARE @current_rows_per_value INT = @rows_per_distinct_value
IF @i <= @distinct_value_count_with_more_rows
BEGIN
SET @current_rows_per_value = @rows_per_distinct_value + 2000
END
SET @j = 1
WHILE @j <= @current_rows_per_value
BEGIN
INSERT INTO myTable (Column1, Column2, Column3, Column4, Column5, Column6, Column7, Column8, Column9, Column10)
VALUES ('Value' + CAST(@i AS VARCHAR(2)),
'Value' + CAST(@j AS VARCHAR(5)),
'Value' + CAST(@j + 1 AS VARCHAR(5)),
'Value' + CAST(@j + 2 AS VARCHAR(5)),
'Value' + CAST(@j + 3 AS VARCHAR(5)),
'Value' + CAST(@j + 4 AS VARCHAR(5)),
'Value' + CAST(@j + 5 AS VARCHAR(5)),
'Value' + CAST(@j + 6 AS VARCHAR(5)),
'Value' + CAST(@j + 7 AS VARCHAR(5)),
'Value' + CAST(@j + 8 AS VARCHAR(5)))
SET @j = @j + 1
END
SET @i = @i + 1
END
Create NonClustered Index Idx_col on MyTable(Column1)
sp_recompile 'dbo.MyTable'
Create or Alter Procedure dbo.tmp_testProc(
@inValue VarChar(50)
)
As
Begin
Set NoCount On
Select Id
Into #tmpCol
From MyTable
Where Column1 = @inValue
Select t.*
From MyTable t
Join #tmpCol tmp
On t.Id = tmp.Id
Order by t.Id
End
--Scenario 1
exec dbo.tmp_testProc @inValue = 'Value1'
--Scenario 2
exec dbo.tmp_testProc @inValue = 'Value5'
我'Value1'
在第一次执行时使用参数值 = 执行存储过程,然后使用'Value5'
. 以下是两种场景的执行计划:
场景 1 执行计划:https://www.brentozar.com/pastetheplan/? id=r1H-3HONh
场景 2 执行计划:https://www.brentozar.com/pastetheplan/? id=r1p42SOE3
我预计第二种情况会采用与第一种情况相同的计划,但我发现计划有所不同。我的印象是优化器会为所有后续执行重用为初始参数集生成的相同计划。因此,我不确定为什么优化器会在这种情况下创建不同的计划。如果对此事有任何澄清,我将不胜感激。谢谢您的帮助。
我有一个包含 1.5 亿条记录和 8 个索引的表。其中一个索引是 on userId
。我过滤了很多当前的查询userId
,因此这个索引工作得很好。对于其中一个查询,我必须扩展 where 子句以包含regionId
和productId
列。我有两个选择:我可以使用这些新列创建一个新索引(userId, regionId, productId)
或将这些新列添加到现有索引中。哪个是更好的选择?如果我修改现有索引,它会影响其他已经使用的查询吗userId
?
我的目标:
我希望我当前的查询扩展 where 子句以包含RegionId
并productId
运行得更快,但我不希望我的其他查询只userId
在 where 子句中受到影响。如果我在上面添加一个新索引,(userid, regional, productid)
我可以做到这一点,但我不确定我是否在复制该索引,因为我已经有一个现有索引,userId
我可以在该索引上扩展以包含regionid
和productId
. 但我不确定修改现有索引的后果。
谢谢你的时间!
我有三个表::product, users, and orders
product
所有产品及其状态的列表。该表有一个名为 的字段previousProductId
。产品的代码可以更改多次,如果是,则将previousProductId
包含它的直接前身代码。例如,如果产品的代码为 1057,然后为该产品添加新代码 1060 的新行,则 previousLineId 的代码将为 1057。每次为新代码添加新行时都会重复此操作现有产品。
users
: list of all users
orders
: 列表所有用户下的订单
现在我必须编写一个查询来获取所有包含活动产品的订单。我必须确保所有订购活动产品以前版本的用户也包含在结果集中。我想使用递归 CTE 沿着链向上检索给定产品的所有先前产品 ID 并以这种方式检索必要的信息,但该方法似乎有点过于庞大。我想知道是否有更好更简单的方法。谢谢你!
Create table #product
(
productId Int primary key Identity(1,1),
name varchar(100),
price numeric(18,5),
previousProductId Int,
active bit
)
Create table #users
(
userId Int Primary key,
name varchar(100)
)
Create table #orders
(
orderId Int primary key,
userId Int,
productId Int
)
Insert Into #product values ('Sony TV', 200.23, null, 0), ('Sony Tv New', 240.43, 1, 0), ('Apple Watch', 300.45, null, 1)
,('Samsung Mobile',1050, null,0),('Sony TV Advanced', 400, 2,1)
Insert Into #users values (1,'John'), (2,'Mary'), (3,'Kevin'), (4,'Joe'), (5,'Andy'),(6,'Jim'),(7,'Pam')
Insert Into #orders values (1, 1, 1), (2, 2, 1),(3, 3,2), (4,4,3), (5,5,3),(6,6,4),(7,7,5)
select t_p.productId, t_p.name, t_p.price, t_p.previousProductId, t_p.active
,t_u.name as username, t_o.orderId
from #product t_p
join #orders t_o
on t_p.productId = t_o.productId
join #users t_u
on t_u.userID = t_o.userId
where t_p.active = 1
drop table if exists #product
drop table if exists #orders
drop table if exists #users
我们有一个在语句SUM
中的 Int 列上使用的存储过程。SELECT
在某些情况下,对于其中一个参数值,SUM(整数列)超出 Int 范围并因此抛出错误
将表达式转换为数据类型 int 时出现算术溢出错误
解决方案是在 sum 函数中将列转换为 bigint,即Sum(Convert(BigInt, column))
。但是,由于此时只有少数特定情况会发生这种情况,而不是所有情况,我担心我最终会惩罚不需要这种转换的其他情况。转换通常会产生多少性能差异?还有其他方法可以处理这个问题吗?谢谢!
我有一个存储过程usp_appdata
,它被我们的应用程序加载屏幕以及应用程序中的许多其他地方使用。这个 SP 非常耗费资源并返回大量数据。我打算制作此存储过程的副本,usp_appdata_initial
并将其仅用于应用程序加载屏幕,并将原始 spusp_appdata
用于所有其他调用。将同一个过程分成多个过程并将每个过程用于特定目的是否会提供任何性能优势?谢谢!
考虑以下场景:
- 10,000 个用户同时尝试在我们的应用程序上创建配置文件,数据必须插入到表 userProfile 中。
- 处理这个插入的 SP 需要半秒的时间来执行。
根据我对锁定和事务的理解,每次插入都会锁定该表。这意味着到创建最后一个用户的配置文件时需要一段时间。SQL Server 如何处理并发更新和锁定?如果对此有任何见解,我将不胜感激。谢谢!
我有一种情况,我必须决定是接收 XML 作为存储过程的输入参数,还是接收逗号分隔值列表,并使用多表值函数解析它们。
从逻辑上讲,我更喜欢 XML 而不是 udfs,因为 udfs 会导致很多性能问题。但我看到后端的 XML 也使用表值函数来解析 xml。我想知道 XML 是否真的比多表 UDF 好,如果是,是什么让它更好?
CREATE FUNCTION [dbo].[tmp_array_commaValues] ( @string varchar(4000))
RETURNS @final TABLE(Value varchar(100))
AS
begin
WITH tmp_cte(start, stop) AS
(
SELECT 1, CHARINDEX(',' , @string )
UNION ALL
SELECT stop + 1, CHARINDEX(',' ,@string , stop + 1)
FROM tmp_cte
WHERE stop > 0
)
insert into @final
SELECT SUBSTRING(@string , start, CASE WHEN stop > 0 THEN stop-start ELSE 4000 END) AS stringValue
FROM tmp_cte
return
end
/* query */
Select value
From [dbo].[tmp_array_commaValues]('TAG,ABC,ZYX,BAG,TRY,LAG,LEAD,NETHERLANDS,TAG1,ABC1,ZYX1,BAG1,TRY1,SUN12,NANGE1')
/********** XML *********/
Declare @xml XML = '<root><id>Tag</id><id>Lag</id>
<id>Tag1</id><id>Lag1</id>
<id>Tag2</id><id>Lag2</id>
<id>Tag3</id><id>Lag3</id>
<id>Tag4</id><id>Lag4</id>
<id>Tag5</id><id>Lag5</id>
<id>Tag6</id><id>Lag6</id>
<id>Tag7</id><id>Lag7</id>
</root>'
select t.c.value('.','varchar(100)') as string
From @xml.nodes('root/id/text()') As t(c)
UDF 的执行计划: https ://www.brentozar.com/pastetheplan/?id=SJpX2DMwi
XML 的执行计划: https ://www.brentozar.com/pastetheplan/?id=ByQv2PMvo
我有 3 个表:
test_productInfo:包含有关产品的信息
test_productCreator:包含我们系统中的所有用户
test_productOwner:包含有关谁是产品所有者的信息。test_productInfo 和 test_productCreator 之间的交叉引用表。
我的存储过程需要一个 productCreatorId 或多个 productCreatorIds 和一个排序键,并返回 test_productInfo(所有列)中按传入的排序键排序的前 1000 行。不幸的是,我必须选择所有内容。
我已经粘贴了我们在下面的当前查询,这是它的执行计划: https ://www.brentozar.com/pastetheplan/?id=SyKgEEVNj
我正在取回 20 个用户的数据。当前查询的排序溢出到 tempdb。
我在 productId 上添加了一个新的非聚集索引,它是聚集键并包含所有排序键。我将查询修改为仅在排序时选择 productId,以便可以使用这个新索引并将结果存储在临时表中。在随后的查询中,我添加了所有需要的列并再次进行排序。This query works well for users who have more than 1000 rows coz' I'm not sorting more than 1000 rows when all the columns are being selected. 对于少于 1000 行的用户,我两次访问 productInfo 表,但我没有观察到当前查询和修改后的查询之间的时间差异很大。这是修改后查询的执行计划:https ://www.brentozar.com/pastetheplan/?id=SyA_SVEVs
使用新的修改后的查询,我正在尝试减少排序溢出,并且我看到了一些改进,尤其是当有超过 1000 行时。
在包含某些列的集群键上创建非集群索引是否有意义?有没有更好的方法来重写我当前的查询?
--drop table test_productInfo
--drop table test_productOwner
--drop table test_productCreator
Create Table test_productInfo
(
productId uniqueIdentifier Primary Key,
productName varchar(100),
productRegion varchar(100),
productCreatedDt Datetime,
productUpdatedDt Datetime,
productStatus varchar(100),
isProductsold bit,
productLineNumber Int,
productLineId uniqueIdentifier,
productAddress varchar(100),
productAddress2 varchar(100),
productCity varchar(100),
productState varchar(100),
productCountry varchar(100),
productZip Varchar(100),
productLatitude varchar(100),
productLongitude varchar(100)
)
Create Table test_productOwner
(
productOwnerId Int Identity(1,1),
productId uniqueIdentifier,
productCreatorId uniqueIdentifier,
Createddate datetime,
modifieddate datetime
)
Create Table test_productCreator
(
productCreatorId uniqueIdentifier primary key,
productCreatorName varchar(100),
createddate datetime,
modifieddate datetime
)
ALTER TABLE test_productOwner ADD CONSTRAINT PK_test_productOwner PRIMARY KEY NONCLUSTERED(productOwnerId)
create clustered index ix_test_productOwner_productId On dbo.test_productOwner(productId)
create nonclustered index ix_test_productOwner_test_productCreatorId On dbo.test_productOwner(productCreatorId)
/* Insert data */
Declare @i int = 1, @j int = 1
Declare @newIdi uniqueidentifier, @newIdj uniqueidentifier
While @i < 100
Begin
set @newIdi = newid()
Insert Into dbo.test_productCreator values (@newIdi, 'ABC'+convert(varchar(10),@i), getdate(),getdate())
while @j <= 2300
Begin
set @newIdj = newId()
Insert Into dbo.test_productInfo values (@newIdj, 'ProductName'+convert(varchar(10),@i)+convert(varchar(10),@j), 'Region1',getdate(),getdate(),'completed', 1, @i,newId()
,'Address1'+convert(varchar(10),@i)+convert(varchar(10),@j), 'Address2'+convert(varchar(10),@i)+convert(varchar(10),@j), 'los angeles','ca','USA','22231','26.45','33.23')
insert into dbo.test_productOwner values (@newIdj, @newIdi, getdate(), getdate())
set @j = @j + 1
End
set @i = @i + 1
set @j = 1
End
**CURRENT Query:**
set statistics io on
Declare @sort varchar(100) = 'PRODMODIFIED'
Declare @PageNumber int = 1, @PageSize int = 1000
Declare @prodCreator Table(productCreatorId Uniqueidentifier)
insert into @prodCreator
select top 10 productCreatorId
from dbo.test_productCreator
Select p_pi.*
from test_productInfo p_pi
join test_productowner p_po
on p_pi.productId = p_po.productId
join @prodcreator p_pc
on p_po.productCreatorId = p_pc.productCreatorId
order by case when @sort = 'PRODMODIFIED' then p_pi.productUpdatedDt
when @sort = 'PRODCREATED' then p_pi.productCreatedDt
when @sort = 'PRODNAME' then p_pi.productName
end
OFFSET @PageSize * (@PageNumber - 1) ROWS
FETCH NEXT @PageSize ROWS ONLY
**MODIFIED Query:**
create nonclustered index idx_non_productInfo on dbo.productInfo(productId) include(productUpdatedDt, productCreatedDt, productName)
set statistics io on
Declare @sort varchar(100) = 'PRODMODIFIED'
Declare @PageNumber int = 1, @PageSize int = 1000
Declare @prodCreator Table(productCreatorId Uniqueidentifier)
Create Table #tmpProduct (productId uniqueidentifier)
insert into @prodCreator
select top 10 productCreatorId
from dbo.test_productCreator
Insert Into #tmpProduct
Select p_pi.productId
from test_productInfo p_pi
join test_productowner p_po
on p_pi.productId = p_po.productId
join @prodcreator p_pc
on p_po.productCreatorId = p_pc.productCreatorId
order by case when @sort = 'PRODMODIFIED' then p_pi.productUpdatedDt
when @sort = 'PRODCREATED' then p_pi.productCreatedDt
when @sort = 'PRODNAME' then p_pi.productName
end
OFFSET @PageSize * (@PageNumber - 1) ROWS
FETCH NEXT @PageSize ROWS ONLY
Select p_pi.*
from #tmpProduct tmp_pi
join test_productInfo p_pi
on tmp_pi.productId = p_pi.productId
join test_productowner p_po
on p_pi.productId = p_po.productId
join @prodcreator p_pc
on p_po.productCreatorId = p_pc.productCreatorId
order by case when @sort = 'PRODMODIFIED' then p_pi.productUpdatedDt
when @sort = 'PRODCREATED' then p_pi.productCreatedDt
when @sort = 'PRODNAME' then p_pi.productName
end
If object_id('tempdb..#tmpProduct') is not null
begin
drop table #tmpProduct
end
我在 SQL Server 2012 中执行了以下查询:
create table testTransaction
(
id int
name varchar(100)
)
insert into testTransaction values (1,'ABC'),(2,'XYZ')
/* Query1 */
begin try
begin transaction
insert into testTransaction values (3,'FGH')
commit transaction
end try
begin catch
if @@trancount > 0
rollback transaction
end catch
我执行了 query1 并得到一个错误,我使用的帐户没有权限将值插入到该表中。在另一个窗口中,我尝试在 testTransaction 上进行选择,但查询一直在继续。
那时我意识到我在另一个窗口中运行的前一个查询有一个打开的事务。我去把它滚回来,一切都很好。
如果我关闭了具有打开事务的窗口而不回滚它会发生什么?事务是否会一直打开,直到有人手动回滚它,或者当窗口关闭时 SQL Server 是否回滚任何未提交的事务?
另外,我如何在任何会话中找出数据库中所有打开的事务?