Оптимизация запроса соединения SQL со сравнением дат

У меня есть запрос, получение 16 900 строк занимает около 2 секунд:

SELECT x.lid
FROM schema1.view1 x
INNER JOIN schema1.view2 y
    ON x.cid = y.cid
        and datediff(day, x.indt, y.linvcy)=0    -- problematic line
        and x.indt = y.indt                      -- alternative line I've tried

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

Каждое из представлений содержит логику соединения, поэтому сложность плана запроса довольно высока. Я ищу несколько указателей, которые помогут оптимизировать этот запрос.

schema1.view1:

select
    D.lid,
    D.cid,
    D.indt,
    lower(trim(substring(C.bse, 1, charindex('-', C.bse)-1))) as bse
from (
    select
        B.lid,
        B.cid,
        B.indt
    from ds.v A
    inner join (
        select
            x.lid,
            x.cid,
            x.ivid,
            x.clior,
            x.sosy,
            x.indt
        from rd.ui x
        where
            x.clior like 'abc'
    ) B
    on
        B.ivid like A.ivn
        and B.clior like A.clior
) D
left join ctlg.brchs C
on
    C.paor like D.clior
    and C.sosy like D.sosy
    and C.bid like D.cid

rd.ui:

create table rd.ui (
    id int identity(1,1) primary key,
    lid varchar(256),
    cid varchar(256),
    ivid varchar(256),
    indt date,
    clior varchar(256),
    sosy varchar(256)
)

create unique index idx_unlid
on rd.ui(lid)

create index idx_sebid
on rd.ui(bid)

create index idx_seindt
on rd.ui(indt)

create index idx_sec
on rd.ui(clior)

ctlg.brchs:

create table ctlg.brchs (
    id int identity(1,1) primary key,
    paor varchar(256),
    sosy varchar(256),
    bid varchar(256)
)
create unique index idx_unbr
on ctlg.brchs (paor, sosy, bid)

schema1.view2:

SELECT 
    A.cid
    , A.cinvcy
    , B.linvcy
FROM (
    SELECT
        x.cid
        , MAX(x.indt) AS cinvcy
    FROM schema1.view1 x
    GROUP BY
        x.cid
) A
INNER JOIN (
    SELECT
        z.cid
        , MAX(z.indt) AS linvcy
    FROM (
        SELECT
            x.cid
            , x.indt
        FROM schema1.view1 x
        WHERE CONCAT(x.cid, x.ind) NOT IN (
            SELECT CONCAT(y.cid, MAX(y.indt))
            FROM schema1.view1 y
            GROUP BY y.cid 
        )
    ) z
    GROUP BY
        z.cid
) B
ON A.cid=B.cid

Я пытался создать индексированные представления с помощью with schemabinding, но эти представления содержат CTE и производные таблицы (select * from (select * from x)), что означает, что я не могу создавать индексы для этих представлений.

ОБНОВЛЕНИЕ: изменение like на = значительно улучшило скорость этой части запроса, но остальная часть по-прежнему работает очень медленно.

Добавьте определения представлений, определения их таблиц и индексы.

jarlh 10.07.2024 22:19

это потому, что каждая запись должна оцениваться индивидуально. Поэтому он должен выполнить полное сканирование таблицы и выполнить dateiff для каждой записи. Возможно, вам лучше создать постоянный вычисляемый столбец для daterdiff, который хранится в одной из таблиц. Возможно, что-то вроде этого: stackoverflow.com/questions/6867047/… . MSFT DOCS, а затем проиндексируйте его.

xQbert 10.07.2024 22:22

Альтернативный подход может заключаться в использовании материализованного представления вместо вычисляемого столбца. Просто зависит от потребностей в данных в реальном времени. в основном он вычисляет значение разницы дат, сохраняет его, а затем необходимо изменить только новые/обновленные записи. Таким образом, соединение/ограничение загружается заранее для приемника времени.

xQbert 10.07.2024 22:27

Почему оценка dateiff для 16900 строк занимает час? Похоже оптимизатор сбился.

jarlh 10.07.2024 22:30

Привет всем, я обновил вопрос более подробно. Пожалуйста, дайте мне знать, если вам нужно что-нибудь еще.

tubular 11.07.2024 01:18

Я проголосовал за возобновление вашего вопроса. Я вижу множество особенностей в предоставленном вами коде. Какую версию SQL Server вы используете?

Alex 11.07.2024 02:43

Почему вы везде используете like? У вас вообще есть подстановочные знаки? Или это способ обработки пробелов при объединении? idiosyncrasies действительно

siggemannen 11.07.2024 08:22

@Алекс, я использую SQL-сервер Azure ... Microsoft SQL Azure (RTM) - 12.0.2000.8 Я понимаю, что запросы выглядят не очень хорошо. Что самое важное мне следует исправить в первую очередь?

tubular 12.07.2024 00:58

@siggemannen Раньше эти столбцы были типа text, который не позволял сравнивать по равенству. С тех пор я изменил эти столбцы на varchar, но на самом деле еще не изменил все like на =.

tubular 12.07.2024 00:59

@siggemannen Пожалуйста, посмотрите обновление внизу поста.

tubular 12.07.2024 01:15
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
10
94
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В schema1.view2 это CONCAT совпадение странное.

SELECT
    x.cid
    , x.indt
FROM schema1.view1 x
WHERE CONCAT(x.cid, x.ind) NOT IN (
    SELECT CONCAT(y.cid, MAX(y.indt))
    FROM schema1.view1 y
    GROUP BY y.cid

Насколько я понимаю, этот запрос пытается исключить «последнее значение» (последнюю дату?) Попробуйте изменить его на:

SELECT x.cid, x.indt
FROM(
    SELECT x.cid, x.indt, ROW_NUMBER() OVER( PARTITION BY cid ORDER BY indt DESC ) AS Maxindt
    FROM schema1.view1 x
     ) AS y
WHERE Maxindt <> 1

Попробуйте добавить следующий индекс в таблицу rd.ui

создать индекс idx_PickYourName в rd.ui(ivid, clior)

Как предложил @siggemannen в комментариях, пожалуйста, замените все совпадения LIKE на =, где это возможно.

Я попробовал ваше решение, но в запросе была синтаксическая ошибка, связанная с where maxindt <> 1, поскольку столбец не определен. Я также добавил указанный индекс, но существенных улучшений не заметил. Однако замена LIKE на = в каждом случае заметно улучшила производительность. На самом деле я бы сказал, что замена более или менее решила мои проблемы с вопросами, представленными здесь.

tubular 13.07.2024 01:18

Я опубликовал еще один (связанный) вопрос с более подробной информацией. Пожалуйста, посмотрите, если у вас есть время. Спасибо. stackoverflow.com/questions/78742499/…

tubular 13.07.2024 01:18

RE "where maxindt <> 1" – извините за ошибку, см. обновленный запрос.

Alex 13.07.2024 02:12

Другие вопросы по теме