SQL Server 2008不使用具有用户定义函数的索引

时间:2016-06-23 06:38:18

标签: sql-server sql-server-2008

在SQL 2008中,我尝试在查询中使用简单的用户定义函数,但SQL服务器不使用索引,并且查询执行时间很长。 有没有办法告诉SQL服务器函数的结果可以在查询中用作简单的数字/文字,它可以使用索引吗?

例如,有三种情况:

1)简单选择(使用索引):

SELECT * FROM [ORDERS] WHERE [CarId] = 5

2)选择变量(不使用索引):

DECLARE @five int = 5;
SELECT * FROM [ORDERS] WHERE [CarId] = @five

2.1)选择变量,(使用索引):

DECLARE @five int = 5;
SELECT * FROM [ORDERS] WHERE [CarId] = @five OPTION (RECOMPILE)

3)在查询中选择用户函数调用(不使用索引)

IF OBJECT_ID (N'dbo.five', N'FN') IS NOT NULL
    DROP FUNCTION dbo.five;

CREATE FUNCTION dbo.five()
RETURNS int
WITH SCHEMABINDING
AS
BEGIN
    RETURN 5;
END;

SELECT * FROM [ORDERS] WHERE [CarId] = dbo.five()

Execution plan

3.1)使用索引,但计划不是最优的

SELECT * FROM [ORDERS] with (index(IDX_CARID)) WHERE [CarId] = dbo.five() 

3.1 Execution plan

表脚本:

CREATE TABLE [ORDERS](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Phone] [varchar](15) NULL,
    [dtBegin] [datetime] NULL,
    [dtEnd] [datetime] NULL,
    [CarID] [int] NULL,
 CONSTRAINT [PK_ORDERS] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (
    PAD_INDEX = OFF, 
    STATISTICS_NORECOMPUTE = OFF, 
    IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS = ON, 
    ALLOW_PAGE_LOCKS = OFF, 
    FILLFACTOR = 90
) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [ORDERS]  WITH CHECK ADD  CONSTRAINT [FK_CARS_ORDERS] FOREIGN KEY([CarID])
REFERENCES [CARS] ([ID])
ON DELETE SET NULL
GO

ALTER TABLE [ORDERS] CHECK CONSTRAINT [FK_CARS_ORDERS]
GO

指数代码:

CREATE NONCLUSTERED INDEX [IDX_CARID] ON [ORDERS]
(
    [CarID] ASC
)WITH (
    PAD_INDEX = OFF, 
    STATISTICS_NORECOMPUTE = OFF, 
    SORT_IN_TEMPDB = OFF, 
    DROP_EXISTING = OFF, 
    ONLINE = OFF, 
    ALLOW_ROW_LOCKS = ON, 
    ALLOW_PAGE_LOCKS = OFF, 
    FILLFACTOR = 90
) ON [PRIMARY]

2 个答案:

答案 0 :(得分:0)

在选择所有字段时,非聚集索引在给定示例中仅为CarID,因此它将始终扫描而不是搜索, 检查在查询下执行的执行计划:

SELECT CarId FROM [ORDERS] WHERE [CarId] = dbo.five()

如果您希望所有其他值都必须包含在非聚簇索引中,则可以创建一个非聚集索引,该索引以所需的选定列为目标

答案 1 :(得分:0)

  1. 当您在where子句中使用函数时,使用索引的可能性非常小。
  2. 为什么您认为3.1执行计划不是查询最佳计划的最佳查询。
    如果您正确观察到索引扫描已被搜索替换,则计划中唯一的问题是密钥查找。当您在查询中有*时,键查找会弹出计划中

    Select * from  table where conditions 
    
  3. 如果您使用特定的列列表,那么性能将仅是最佳的,而不是选择*,但我仍然不会说密钥查找组件将被减少,但这一切都取决于您选择的要求。

    由于