У меня есть запрос, получение 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
на =
значительно улучшило скорость этой части запроса, но остальная часть по-прежнему работает очень медленно.
это потому, что каждая запись должна оцениваться индивидуально. Поэтому он должен выполнить полное сканирование таблицы и выполнить dateiff для каждой записи. Возможно, вам лучше создать постоянный вычисляемый столбец для daterdiff, который хранится в одной из таблиц. Возможно, что-то вроде этого: stackoverflow.com/questions/6867047/… . MSFT DOCS, а затем проиндексируйте его.
Альтернативный подход может заключаться в использовании материализованного представления вместо вычисляемого столбца. Просто зависит от потребностей в данных в реальном времени. в основном он вычисляет значение разницы дат, сохраняет его, а затем необходимо изменить только новые/обновленные записи. Таким образом, соединение/ограничение загружается заранее для приемника времени.
Почему оценка dateiff для 16900 строк занимает час? Похоже оптимизатор сбился.
Привет всем, я обновил вопрос более подробно. Пожалуйста, дайте мне знать, если вам нужно что-нибудь еще.
Я проголосовал за возобновление вашего вопроса. Я вижу множество особенностей в предоставленном вами коде. Какую версию SQL Server вы используете?
Почему вы везде используете like
? У вас вообще есть подстановочные знаки? Или это способ обработки пробелов при объединении? idiosyncrasies
действительно
@Алекс, я использую SQL-сервер Azure ... Microsoft SQL Azure (RTM) - 12.0.2000.8
Я понимаю, что запросы выглядят не очень хорошо. Что самое важное мне следует исправить в первую очередь?
@siggemannen Раньше эти столбцы были типа text
, который не позволял сравнивать по равенству. С тех пор я изменил эти столбцы на varchar, но на самом деле еще не изменил все like
на =
.
@siggemannen Пожалуйста, посмотрите обновление внизу поста.
В 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
на =
в каждом случае заметно улучшила производительность. На самом деле я бы сказал, что замена более или менее решила мои проблемы с вопросами, представленными здесь.
Я опубликовал еще один (связанный) вопрос с более подробной информацией. Пожалуйста, посмотрите, если у вас есть время. Спасибо. stackoverflow.com/questions/78742499/…
RE "where maxindt <> 1
" – извините за ошибку, см. обновленный запрос.
Добавьте определения представлений, определения их таблиц и индексы.