Настройка запросов SQL Server 2008 - PullRequest
3 голосов
/ 06 апреля 2011

У меня есть имя представления "vw_AllJobsWithRecruiter".

ALTER VIEW dbo.vw_AllJobsWithRecruiter
AS
SELECT TOP(SELECT COUNT(iJobID_PK) FROM dbo.tbUS_Jobs)
         iJobId_PK AS JobId,
         dbo.ufn_JobStatus(iJobId_PK) AS JobStatus,
         dbo.ufn_RecruiterCompanyName(iJobId_PK) AS CompanyName,
         sOther AS OtherCompanyName
FROM dbo.tbUS_Jobs
WHERE bDraft = 0
ORDER BY dtPostedDate DESC

Это представление содержит только 3278 строк.

Если я выполню следующий запрос:

SELECT * FROM vw_AllJobsWithRecruiter
WHERE  OtherCompanyName LIKE '%Microsoft INC%'

Выполнение занимает менее секунды.

Теперь моя проблема:

Если я использую запрос ниже запроса:

SELECT * FROM vw_AllJobsWithRecruiter
WHERE CompanyName LIKE '%Microsoft INC%' 
      OR OtherCompanyName LIKE '%Microsoft INC%'

Это занимает 30секунд, чтобы выполнить, и от переднего конца это выбрасывает ошибку времени ожидания.Функция здесь:

CREATE Function [dbo].[ufn_RecruiterCompanyName] (@JobId bigint)      
RETURNS nvarchar(200)      
AS      
BEGIN      
 DECLARE @ResultVar nvarchar(200)     
 DECLARE @RecruiterId bigint     

 select @RecruiterId = iRecruiterId_FK from dbo.tbUS_Jobs     with (Nolock)   
 where iJobId_PK = @JobId;      

 Select @ResultVar = sCompanyName from dbo.tbUS_RecruiterCompanyInfo     with (Nolock)   
 where iRecruiterId_FK = dbo.ufn_GetParentRecruiterID(@RecruiterId)      

 return isnull(@ResultVar,'')      

END 

Другая функция

CREATE Function [dbo].[ufn_GetParentRecruiterID](@RecruiterId bigint)  
returns bigint  
as  
begin   
declare @ParentRecruiterId bigint  

SELECT @ParentRecruiterId = iParentId FROM dbo.tbUS_Recruiter with (Nolock)   
WHERE iRecruiterId_PK = @RecruiterId  

IF(@ParentRecruiterId = 0)  
 SET @ParentRecruiterId = @RecruiterId  

RETURN @ParentRecruiterId  
end 

Мои вопросы

  1. Почему выполнение занимает так много времени?
  2. Как я могу сократить время выполнения?

Большое спасибо за ваше внимание.

Ответы [ 2 ]

4 голосов
/ 06 апреля 2011

Первый запрос вызывает только dbo.ufn_RecruiterCompanyName() только для возвращенных строк, он фильтрует по сохраненному значению.Для второго запроса SQL Server должен вызвать ufn для всех строк.В зависимости от функции это может вызвать задержку.

Проверьте это в Query Analyzer и попытайтесь избежать второго запроса ^^

После просмотра пользовательской функции я предлагаю переписатьПросмотр с использованием объединенных таблиц.При выполнении поиска в таких функциях SQL Server вызывает их для каждой строки, которую он касается или доставляет.Использование LEFT JOIN позволяет Серверу использовать индексы и ключи гораздо быстрее и должно доставлять данные менее чем за секунду.

Без всех пользовательских функций и определения всех таблиц я не могу датьВы пример этого нового вида, но он должен выглядеть примерно так:

SELECT
    jobs.Jobid,
    jobstatus.Jobstatus,
    recruiter.Company
FROM jobs
LEFT JOIN jobstatus ON jobs.Jobid = jobstatus.Jobid
LEFT JOIN recruiter ON jobs.Recruiterid = recruiter.Recruiterid
1 голос
/ 06 апреля 2011

Проблема заключается в вызовах вложенных функций.

Вы вызываете ufn_RecruiterCompanyName в своем предложении WHERE, хотя и косвенно.

Что это означает, ваше предложение WHEREnon- Sargable и должен запускать эту функцию для каждой строки .

Эта функция также вызывает ufn_GetParentRecruiterID.Так как это есть в вашем предложении WHERE в первой функции и также не относится к Sargable, вы в основном выполняете два сканирования таблицы для каждой строки в таблице.

Замените вызовы функций на JOIN s, и выувидит огромный прирост производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...