我目前正在维护一个至少有10个遗留应用程序使用它的数据库。这真的是一个很长的故事,所以我不会详细介绍它。
在数据库中,我们有一个包含以下代码的视图:
CREATE VIEW [dbo].[vw_ViewControl]
AS
SELECT
'CAX1' AS table_name,
max(convert(datetime,txn_pDate)) AS curr_dt,
(
SELECT MAX(CONVERT(datetime,txn_pDate))
FROM tbl_txn WITH(NOLOCK)
WHERE CONVERT(datetime,txn_pDate) <
(
SELECT MAX(CONVERT(datetime,txn_pDate))
FROM tbl_txn WITH(NOLOCK))
) AS prev_dt,
MAX(DateCreated) AS final_updte
FROM tbl_txn WITH(NOLOCK) UNION ALL
SELECT
'CAX2' AS table_name,
max(convert(datetime,txn_pDate)) AS curr_dt,
(
SELECT MAX(CONVERT(datetime,txn_pDate))
FROM tbl_txn WITH(NOLOCK)
WHERE CONVERT(datetime,txn_pDate) <
(
SELECT MAX(CONVERT(datetime,txn_pDate))
FROM tbl_txn WITH(NOLOCK))
) AS prev_dt,
MAX(DateCreated) AS final_updte
FROM tbl_txn WITH(NOLOCK) UNION ALL
SELECT
'CAX3' AS table_name,
max(convert(datetime,txn_pDate)) AS curr_dt,
(
SELECT MAX(CONVERT(datetime,txn_pDate))
FROM tbl_txn WITH(NOLOCK)
WHERE CONVERT(datetime,txn_pDate) <
(
SELECT MAX(CONVERT(datetime,txn_pDate))
FROM tbl_txn WITH(NOLOCK))
) AS prev_dt,
MAX(DateCreated) AS final_updte
FROM tbl_txn WITH(NOLOCK) UNION ALL
SELECT
'CAX4' AS table_name,
max(convert(datetime,txn_pDate)) AS curr_dt,
(
SELECT MAX(CONVERT(datetime,txn_pDate))
FROM tbl_txn WITH(NOLOCK)
WHERE CONVERT(datetime,txn_pDate) <
(
SELECT MAX(CONVERT(datetime,txn_pDate))
FROM tbl_txn WITH(NOLOCK))
) AS prev_dt,
MAX(DateCreated) AS final_updte
FROM tbl_txn WITH(NOLOCK)
为了提高性能,我用这个替换了代码。
CREATE FUNCTION dbo.udf_vw_ViewControl()
RETURNS @M_Control TABLE
(
table_name varchar(15) not null,
curr_dt datetime not null,
prev_dt datetime not null,
final_updte datetime not null
)
AS
BEGIN
declare
@curr_dt datetime,
@prev_dt datetime,
@final_updte datetime
SELECT
@curr_dt = max(convert(datetime,txn_pDate)),
@final_updte = MAX(DateCreated)
FROM
tbl_txn WITH(NOLOCK)
SELECT @prev_dt = MAX(CONVERT(datetime,txn_pDate))
FROM
tbl_txn WITH(NOLOCK)
WHERE
CONVERT(datetime,txn_pDate) < @curr_dt
INSERT @M_Control VALUES( 'ACCOUNT', @curr_dt, @prev_dt, @final_updte )
INSERT @M_Control VALUES( 'CARDHLDR', @curr_dt, @prev_dt, @final_updte )
INSERT @M_Control VALUES( 'CUSTOMER', @curr_dt, @prev_dt, @final_updte )
INSERT @M_Control VALUES( 'TRANSACTNS', @curr_dt, @prev_dt, @final_updte )
RETURN
END
GO
--================== ALTER VIEW
ALTER VIEW [dbo].[vw_ViewControl]
AS
SELECT
xControl.table_name
, xControl.curr_dt
, xControl.prev_dt
, xControl.final_updte
FROM
dbo.udf_vw_ViewControl() xControl
GO
在应用程序中使用的原始视图运行大约4-5分钟。使用UDF的更新视图在至少15分钟内出乎意料地慢得多。我期待更新的视图会更快,因为我已经删除了查询的冗余部分。
任何想法为什么?或者还有另一种方法会更快吗?
非常感谢。
答案 0 :(得分:1)
从第一个视图中我看到了性能问题:
CONVERT(datetime,txn_pDate) < @curr_dt
因为convert
索引即使存在也不使用
你能提供执行计划来产生另一个想法吗?
答案 1 :(得分:0)
弗拉基米尔在那里有钱我会在那个
上添加计算列和索引ALTER TABLE tbl_txn ADD txn_pDate_Date AS
CASE WHEN ISDATE(txn_pDate) = 1 THEN CONVERT(DATETIME, txn_pDate) ELSE NULL END
然后,您可以索引计算列
CREATE INDEX IDX_tbl_txn_txn_pDate_Date ON dbo.tbl_txn (txn_pDate_Date)
然后更新原始视图以引用计算列,如果问题中包含所有相关信息,您应该看到改进