Rus*_*sty 6 sql sql-server indexing
我有一个数据库表,其中包含客户详细信息,当他们打电话时,我们使用他们的电话查找他们的详细信息,但这通常需要大约2-3秒,但最近它花了5秒没有额外的数据.如果我使用home_phone_no ='441903354676'查询表,则返回sub seconds.但如果使用home_phone_no ='441903354676'或business_phone_no ='441903354676'进行查询,则需要5秒钟.
现在有大约140万的客户记录.但是,如果任何人都可以看到任何明显的或提供一些有用的建议,这是最受欢
这是表的结构
CREATE TABLE [dbo].[CCDB_ICR]
(
[bill_account_no] [varchar](10) NOT NULL,
[reference_id] [varchar](11) NULL,
[bill_account_status] [varchar](2) NULL,
[customer_type] [varchar](1) NULL,
[customer_name] [varchar](56) NULL,
[property_address] [varchar](69) NULL,
[outer_post_code] [varchar](4) NULL,
[inner_post_code] [varchar](3) NULL,
[customer_move_in_date] [datetime2](7) NULL,
[customer_move_out_date] [datetime2](7) NULL,
[debt_flag] [varchar](1) NULL,
[payment_category_flag] [varchar](2) NULL,
[payment_plan_flag] [varchar](1) NULL,
[key_customer_flag] [varchar](1) NULL,
[home_phone_no] [varchar](12) NULL,
[business_phone_no] [varchar](12) NULL,
[contact_type] [varchar](4) NULL,
[contact_code] [varchar](1) NULL,
[contact_method] [varchar](1) NULL,
[contact_date] [date] NULL,
[contact_time] [varchar](5) NULL,
[contact_status] [varchar](1) NULL,
[contact_unit_resp] [varchar](4) NULL,
[outstanding_balance] [decimal](9, 2) NULL,
[date_time_inserted] [datetime] NOT NULL,
[date_time_updated] [datetime] NULL,
CONSTRAINT [PK_CCDB_ICR]
PRIMARY KEY CLUSTERED([bill_account_no] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
这是索引的结构:
CREATE NONCLUSTERED INDEX [NC_Business&Home_Phone$CCDB_ICR]
ON [dbo].[CCDB_ICR] ([home_phone_no] ASC, [business_phone_no] ASC)
INCLUDE ([bill_account_no])
Run Code Online (Sandbox Code Playgroud)
这是存储过程
ALTER procedure [dbo].[GET_ACCOUNT_BY_PHONE_NUMBER]
(
@CLI varchar(12),
@RETURN_VALUE int out,
@NUMBER_OF_ACCOUNTS int out,
@ACCOUNT_NUMBER varchar(10) out
)
as
Begin Try
declare @ret int
Select @ret=COUNT(*) from CCDB_ICR where home_phone_no=@CLI or business_phone_no=@CLI
if @ret=0
select @RETURN_VALUE=0,
@NUMBER_OF_ACCOUNTS=0,
@ACCOUNT_NUMBER=null
else if @ret=1
select @RETURN_VALUE=0,
@NUMBER_OF_ACCOUNTS=1,
@ACCOUNT_NUMBER=(Select bill_account_no from CCDB_ICR where home_phone_no=@CLI or business_phone_no=@CLI)
else if @ret>1
select @RETURN_VALUE=0,
@NUMBER_OF_ACCOUNTS=@ret ,
@ACCOUNT_NUMBER=null
end Try
Begin Catch
select @RETURN_VALUE=-1,
@NUMBER_OF_ACCOUNTS=null ,
@ACCOUNT_NUMBER=null
End Catch
Run Code Online (Sandbox Code Playgroud)
索引不能用于home_phone_no = '441903354676' or business_phone_no = '441903354676',但它可以用于home_phone_no = '441903354676' and business_phone_no = '441903354676'.
如果索引键的第一列没有条件,它将无法使用索引键的第二列.
要使用or,您可以使用单独的支持索引,例如:
create nonclustered index [NC_Business&Home_Phone$CCDB_ICR]
on [dbo].[CCDB_ICR] ([home_phone_no] asc);
create nonclustered index [NC_Business&Business_Phone$CCDB_ICR]
on [dbo].[CCDB_ICR] ([business_phone_no] asc);
Run Code Online (Sandbox Code Playgroud)
此外,您不需要[bill_account_no]在索引中包含作为包含列,因为它是群集键,因此已经隐式包含.
您可以将整个过程简化为:
alter procedure [dbo].[get_account_by_phone_number] (
@cli varchar(12)
, @return_value int out
, @number_of_accounts int out
, @account_number varchar(10) out
) as
begin;
set nocount, xact_abort on;
set @return_value = 0;
set @number_of_accounts = 0;
select
@number_of_accounts = count(*)
, @account_number = case when count(*)=1 then max(bill_account_no) else null end
from ccdb_icr
where home_phone_no=@cli
or business_phone_no=@cli;
end;
go
Run Code Online (Sandbox Code Playgroud)
如果在创建适当的索引并更新过程后仍遇到性能问题,则应尝试确定参数嗅探是否导致问题.
我将从保罗怀特的这篇文章开始,其中包括以下内容:
SQL Server提供了一系列查询提示和其他选项来调整参数嗅探的行为:
- OPTIMIZE FOR(@parameter = value)查询提示基于特定值构建可重用计划
- OPTIMIZE FOR(@parameter UNKNOWN)使用特定参数的平均分布统计信息
- OPTIMIZE FOR UNKNOWN使用所有参数的平均分布(与跟踪标志4136相同的效果)
- WITH RECOMPILE存储过程选项为每次执行编译新的过程计划
- OPTION(RECOMPILE)查询提示为单个语句编译新计划
〜参数嗅探,嵌入和RECOMPILE选项--Paul White
| 归档时间: |
|
| 查看次数: |
110 次 |
| 最近记录: |