Идентичный план запроса с радикально отличной производительностью, основанный на одном невероятном параметре? - PullRequest
0 голосов
/ 23 сентября 2011

У меня есть специальный запрос, который должен быть довольно быстрым (у меня есть опыт работы администратором баз данных, и я довольно хорош в оптимизации), и почти во всех случаях это так.ОДНАКО, когда я предоставляю конкретный параметр для запроса (довольно избирательное значение с ожидаемым набором результатов, меньшим, чем в среднем), база данных tempdb начинает расти и умирает, когда у него заканчивается диск.

Это одно-отчет о времени для системы Lawson AP в системе SQL Server 2005, если кого-то волнует.

Я проверил планы запросов по выполненному и неисполненному прогонам, не только оценочные планы запросов, но и фактическиепланы запросов, и они абсолютно идентичны.Я обновил статистику и планы запросов остаются идентичными.Единственное, что должно отличаться, - это фактические данные.

Данные для неформатной группы выглядят странно ... столбцы идентификаторов - это char (9) и char (22), левые пробелы, а затем дополненные нулидобавлено для хорошей меры.Типичным значением идентификатора может быть что-то вроде

'    00112'

..., что странно, но это допустимый символ (9) и, следовательно, допустимый.Столбцы хорошо проиндексированы, как и во всех случаях, кроме одного, это работает довольно хорошо.

Я думаю, что проблема связана с индексами, работающими с данными, хотя я не понимаю, как это сделать.Количество записей результатов для неформального запроса меньше половины числа самых больших, которые возвращают результаты в секундах.

запрос, который я использую, выглядит следующим образом (это против схемы базы данных Lawson v9):

insert into dbo.rptPayments with (tablock)
    (
    VendorGroup,
    VendorID,
    VendorName,
    ChargedToCompany,
    ChargedToAccount,
    ChargedToSubAccount,
    InvoiceID,
    PaymentAmount
    )
select top 100 percent
    vm.VENDOR_GROUP as VendorGroup,
    rtrim(ltrim(vm.VENDOR)) as VendorID,
    vm.VENDOR_VNAME as VendorName,
    gm.NAME as ChargedToCompany,
    dist.DIS_ACCOUNT as ChargedToAccount,
    dist.DIS_SUB_ACCT as ChargedToSubAccount,
    inv.INVOICE as InvoiceID,
    dist.ORIG_TRAN_AMT as PaymentAmount
from
    dbo.APVENMAST vm with (nolock)
inner join
    dbo.APINVOICE inv with (nolock)
    on inv.VENDOR = vm.VENDOR
    and inv.VENDOR_GROUP = vm.VENDOR_GROUP
inner join
    dbo.APDISTRIB dist with (nolock)
    on dist.COMPANY = inv.COMPANY
    and dist.VENDOR = inv.VENDOR
    and dist.INVOICE = inv.INVOICE
inner join
    dbo.APPAYMENT pay with (nolock)
    on pay.COMPANY = inv.COMPANY
    and pay.VENDOR = vm.VENDOR
    and pay.INVOICE = inv.INVOICE
    and pay.VENDOR_GROUP = inv.VENDOR_GROUP
inner loop join
    dbo.GLSYSTEM gm with (nolock, index(GLSSET1))
    on gm.COMPANY = dist.DIST_COMPANY
where
    vm.VENDOR_GROUP = @VendorGroup
    and vm.VENDOR_STATUS = 'A'
    and inv.INVOICE_DTE between '2009-09-01' and '2011-08-31'
    and pay.VOID_SEQ = 0
    and pay.CANCEL_SEQ = 0

... как вы видите, я использую некоторые подсказки, чтобы направить запрос по правильному пути ... оптимизатор делал некоторые действительно неудачные выборы.Я ожидаю результирующий набор из 20000 - 30000 записей.

Схемы для ссылочных таблиц можно найти здесь .

Определения для пользовательских индексов, которые я создалдля этого:

CREATE NONCLUSTERED INDEX [tmpAPDISTRIB] ON [dbo].[APDISTRIB] 
(
    [COMPANY] ASC,
    [VENDOR] ASC,
    [INVOICE] ASC
)
INCLUDE ( [DIST_COMPANY],
[ORIG_TRAN_AMT],
[DIS_ACCOUNT],
[DIS_SUB_ACCT]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [tmpAPPAYMENT] ON [dbo].[APPAYMENT] 
(
    [COMPANY] ASC,
    [VENDOR] ASC,
    [INVOICE] ASC,
    [VENDOR_GROUP] ASC
)
INCLUDE ( [VOID_SEQ],
[CANCEL_SEQ]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [tmpAPINVOICE] ON [dbo].[APINVOICE] 
(
    [VENDOR] ASC,
    [VENDOR_GROUP] ASC,
    [INVOICE_DTE] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

Любая помощь или предложение будут чрезвычайно полезны.

ОБНОВЛЕНИЕ После более глубокого исследования я обнаружил, что записи из проблемы @VendorGroup хранились по-разному ... по-видимому, в AP Distributions (представленной в таблице dbo.APDISTRIB) есть функциональные возможности для поддержки "повторяющихся" счетов с тем же номером счета, что приводило к декартовому произведению в моих объединениях, как я не имелприсоединился к этой колонке.Ни одна другая группа поставщиков не использовала эту функцию.

1 Ответ

0 голосов
/ 18 апреля 2012

Согласно моему обновлению, план запроса выглядел иначе, потому что одна компания использовала таблицу значительно больше, чем любая другая.

...