Я написал довольно простую хранимую процедуру, которая принимает некоторые данные, выбирает значение, вставляет пару записей и затем возвращает это значение. Но выполнение слишком велико в нашей производственной среде, где я, возможно, в конечном итоге захочу, чтобы он запускал несколько сотен тысяч раз в день, и это отрицательно влияет на другие процессы, даже когда мы его запускаем только 30000 раз.Могу ли я улучшить производительность этого запроса или получить тот же результат с помощью более эффективного процесса?
Я начал с рассмотрения запросов и добавления индекса в поле даты, которое используется в предложениях where. Затем я запустил SQL Server Profiler - подачу результатов в Tuning Advisor и реализацию предложений по индексированию, с которыми он столкнулся. Раньше я видел, что этот инструмент вызывал действительно уродливые индексы, но на этот раз он просто хотел получить одно добавление, и я добавил его. Каждый из этих шагов помог. Но все еще слишком медленно.
Было легко понять, что первым запросом был захват, а не две вставки, где почти мгновенно. Так вот что я имел в то время, в том числе подзапросов времен хода:
--all combined, this typically takes in the range of 1200-1500 ms but occasionally spikes up to ~2200 ms
select coalesce(
(
--when the following is run, this takes ~690 ms
select MIN(maxes.imbsn)
from (
--when the following is run without the higher limiting scopes, this takes ~3600 ms
select imbsn, MAX(assignmentDate) maxAD
from imbsnAssignments
group by imbsn
) maxes
where datediff(d, maxes.maxAD, GETDATE()) > 90
)
,
(
--this is rarely executed but takes ~0 ms when it is
select max(imbsn)+1 from imbsnAssignments
)
)
Основываясь на те времена, казалось, что сливается был отвод вещи (это то, что я себе представить, я мог проверить с исполнением план, если бы я когда-либо выяснял, как его читать, но у меня нет - планы остаются в основном непрозрачными для моего бедного мозга). Чтобы избавиться от коалесценции, я изменил запрос на:
--this runs ~480-700 ms
select MIN(maxes.imbsn)
from (
select imbsn, MAX(assignmentDate) maxAD
from imbsnAssignments
group by imbsn
union
select max(imbsn)+1, getDate()
from imbsnAssignments
) maxes
where datediff(d, maxes.maxAD, GETDATE()) > 90
, что является большим улучшением. Но это все еще довольно медленно.
Я проверил, что советник по настройке профилировщика все еще не хотел, чтобы я вносил какие-либо изменения, прежде чем приходить сюда, чтобы спросить вас об этом. Я думаю, что это оставляет мне два подхода: 1) поддерживать базовый алгоритм, но сжимать большую эффективность из него или 2) переключиться на какой-то более умный способ получить тот же базовый эффект с помощью методов, о которых я не знаю, но одно будет очевидно к одному из вас, крупным мозгам, которые вынюхивают, что я занимаюсь каким-то анти-узором здесь.
Заранее благодарим за внимание и внимание!
Я не совсем уверен, какой ожидаемый формат для этой дополнительной информации, но я попробую. Стол:
CREATE TABLE [dbo].[imbsnAssignments](
[id] [int] IDENTITY(1,1) NOT NULL,
[imbsn] [int] NOT NULL,
[assignmentDate] [date] NOT NULL,
[jobCode] [varchar](10) NOT NULL,
[name] [varchar](45) NOT NULL,
[a1] [varchar](45) NOT NULL,
[a2] [varchar](45) NOT NULL,
[a3] [varchar](45) NOT NULL,
[a4] [varchar](45) NOT NULL,
[city] [varchar](40) NOT NULL,
[state] [char](10) NOT NULL,
[zip] [varchar](10) NOT NULL,
[batchIdent] [varchar](256) NOT NULL,
CONSTRAINT [PK_imbsnAssignments] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
, и я подозреваю, что это не 'правильный' способ показать индексы, но:
TableName IndexName IndexType
imbsnAssignments PK_imbsnAssignments CLUSTERED
imbsnAssignments IX_imbsnAssignments_assignmentDate NONCLUSTERED
imbsnAssignments _dta_index_imbsnAssignments_36_149575571__K2_3 NONCLUSTERED
План выполнения:
|--Stream Aggregate(DEFINE:([Expr1013]=MIN([partialagg1018])))
|--Concatenation
|--Stream Aggregate(DEFINE:([partialagg1018]=MIN([IMB].[dbo].[imbsnAssignments].[imbsn])))
| |--Filter(WHERE:([Expr1003]<dateadd(day,(-90),getdate())))
| |--Stream Aggregate(GROUP BY:([IMB].[dbo].[imbsnAssignments].[imbsn]) DEFINE:([Expr1003]=MAX([IMB].[dbo].[imbsnAssignments].[assignmentDate])))
| |--Index Scan(OBJECT:([IMB].[dbo].[imbsnAssignments].[_dta_index_imbsnAssignments_36_149575571__K2_3]), ORDERED FORWARD)
|--Stream Aggregate(DEFINE:([partialagg1018]=MIN([Expr1009])))
|--Compute Scalar(DEFINE:([Expr1009]=[Expr1008]+(1)))
|--Stream Aggregate(DEFINE:([Expr1008]=MAX([IMB].[dbo].[imbsnAssignments].[imbsn])))
|--Top(TOP EXPRESSION:((1)))
|--Index Scan(OBJECT:([IMB].[dbo].[imbsnAssignments].[_dta_index_imbsnAssignments_36_149575571__K2_3]), ORDERED BACKWARD)
Вы пробовали UNION все? Ваши профсоюзные запросы выглядят так, как будто они взаимно исключают мне. – HLGEM
Опубликуйте план запроса и определение таблицы, включая любые ключи и индексы. – RBarryYoung
Вы можете задать этот вопрос на странице [Обзор кода] (http://codereview.stackexchange.com/). – Jesse