我有一个非常重要,非常缓慢的观点,它的where子句中包含一些非常丑陋的条件。我也知道联接是粗联接和慢联接,varchar(13)
而不是整数标识字段,但想改进下面使用此视图的简单查询:
CREATE VIEW [dbo].[vwReallySlowView] AS
AS
SELECT
I.booking_no_v32 AS bkno,
I.trans_type_v41 AS trantype,
B.Assigned_to_v61 AS Assignbk,
B.order_date AS dateo, B.HourBooked AS HBooked,
B.MinBooked AS MBooked, B.SecBooked AS SBooked,
I.prep_on AS Pon, I.From_locn AS Flocn,
I.Trans_to_locn AS TTlocn,
(CASE I.prep_on WHEN 'Y' THEN I.PDate ELSE I.FirstDate END) AS PrDate, I.PTimeH AS PrTimeH, I.PTimeM AS PrTimeM,
(CASE WHEN I.RetnDate < I.FirstDate THEN I.FirstDate ELSE I.RetnDate END) AS RDatev, I.bit_field_v41 AS bitField, I.FirstDate AS FDatev, I.BookDate AS DBooked,
I.TimeBookedH AS TBookH, I.TimeBookedM AS TBookM, I.TimeBookedS AS TBookS, I.del_time_hour AS dth, I.del_time_min AS dtm, I.return_to_locn AS rtlocn,
I.return_time_hour AS rth, I.return_time_min AS rtm, (CASE WHEN I.Trans_type_v41 IN (6, 7) AND (I.Trans_qty < I.QtyCheckedOut)
THEN 0 WHEN I.Trans_type_v41 IN (6, 7) AND (I.Trans_qty >= I.QtyCheckedOut) THEN I.Trans_Qty - I.QtyCheckedOut ELSE I.trans_qty END) AS trqty,
(CASE WHEN I.Trans_type_v41 IN (6, 7) THEN 0 ELSE I.QtyCheckedOut END) AS MyQtycheckedout, (CASE WHEN I.Trans_type_v41 IN (6, 7)
THEN 0 ELSE I.QtyReturned END) AS retqty, I.ID, B.BookingProgressStatus AS bkProg, I.product_code_v42, I.return_to_locn, I.AssignTo, I.AssignType,
I.QtyReserved, B.DeprepOn,
(CASE B.DeprepOn
WHEN 1 THEN B.DeprepDateTime
ELSE I.RetnDate
END) AS DeprepDateTime, I.InRack
FROM dbo.tblItemtran AS I
INNER JOIN -- booking_no = varchar(13)
dbo.tblbookings AS B ON B.booking_no = I.booking_no_v32 -- string inner-join
INNER JOIN -- product_code = varchar(13)
dbo.tblInvmas AS M ON I.product_code_v42 = M.product_code -- string inner-join
WHERE (I.trans_type_v41 NOT IN (2, 3, 7, 18, 19, 20, 21, 12, 13, 22)) AND (I.trans_type_v41 NOT IN (6, 7)) AND (I.bit_field_v41 & 4 = 0) OR
(I.trans_type_v41 NOT IN (6, 7)) AND (I.bit_field_v41 & 4 = 0) AND (B.BookingProgressStatus = 1) OR
(I.trans_type_v41 IN (6, 7)) AND (I.bit_field_v41 & 4 = 0) AND (I.QtyCheckedOut = 0) OR
(I.trans_type_v41 IN (6, 7)) AND (I.bit_field_v41 & 4 = 0) AND (I.QtyCheckedOut > 0) AND (I.trans_qty - (I.QtyCheckedOut - I.QtyReturned) > 0)
该视图通常如下使用:
select * from vwReallySlowView
where product_code_v42 = 'LIGHTBULB100W' -- find "100 watt lightbulb" rows
当我运行它,我得到这个执行计划项目成本核算批次的总成本的20%到80%,与谓语CONVERT_IMPLICIT( .... &(4))
表明这似乎是很慢的,在做这些bitwise boolean tests
喜欢(I.ibitfield & 4 = 0)
。
我通常不是MS SQL或DBA类型工作的专家,因为大多数时候我都是非SQL软件开发人员。但是我怀疑这样的按位组合不是一个好主意,最好具有离散的布尔字段。
我可以以某种方式改善此索引,以更好地处理此视图,而无需更改架构(已经在数千个位置的生产环境中使用),或者必须更改将几个布尔值打包成整数的基础表bit_field_v41
,以解决此问题。 ?
这tblItemtran
是此执行计划中要扫描的我的聚集索引:
-- goal: speed up select * from vwReallySlowView where productcode = 'X'
CREATE CLUSTERED INDEX [idxtblItemTranProductCodeAndTransType] ON [dbo].[tblItemtran]
(
[product_code_v42] ASC, -- varchar(13)
[trans_type_v41] ASC -- int
)WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
这是其他产品之一的执行计划,该执行结果使该CONVERT_IMPLICIT
谓词的成本为27%。更新请注意,在这种情况下,我的最差节点现在是“”上的“哈希匹配” inner join
,花费34%。摆脱。INNER JOIN
上面视图中的两个操作都在varchar(13)
字段上。
右下角放大:
整个执行计划如.sqlplan在skydrive上可用。此图像只是视觉概述。单击此处单独查看图像。
更新发布的整个执行计划。我似乎找不到product_code
病理上不好的价值,但是做到这一点的一种方法是,select count(*) from view
而不是制造单一产品。但是仅在基础表中的记录中使用5%或更少的产品似乎显示出较低的CONVERT_IMPLICIT
运营成本。如果要在此处修复SQL,我想我会WHERE
在视图中使用Gross 子句,并将该巨大的where-clause-condition的结果作为“ IncludeMeInTheView”位字段存储并存储在基础表中。Presto,问题解决了,对吧?
product_code
使用87%
我的数据来生成该病理案例的值。现在显示图像27%
。再次,为我的编辑造成的混乱表示歉意。