У меня есть то, что кажется коррумпированным индексом?SQL Server LEFT JOIN не соответствует строкам без подсказки JOIN
Вот что происходит. У меня есть две таблицы-функции, первая из которых представляет собой набор случаев, а вторая - набор значащих дат. Эти два набора имеют отношение 1 (случай) к 0 или 1 (осведомленная дата). Обычно я запрашиваю их;
SELECT c.CaseID, a.AwareDate
FROM Cases(@date) AS c
LEFT JOIN AwareDates(@date) AS a ON c.CaseID = a.CaseID;
Проблема в том, что не все строки из AwareDates, которые соответствуют JOIN'd. Если я добавлю подсказку соединения, то они сделают это. сказать;
SELECT c.CaseID, a.AwareDate
FROM Cases(@date) AS c
LEFT MERGE JOIN AwareDates(@date) AS a ON c.CaseID = a.CaseID;
Что я замечаю от плана запроса является то, что добавив намек присоединиться добавляет то из AwareDate данных до того, как присоединиться к которой не существует иначе. Кроме того, планировщик запросов переворачивает соединение в ПРАВИЛЬНУЮ ВНУТРЕННУЮ СОЕДИНЕНИЕ, когда нет намека, и, конечно, держит ЛЕВЫЙ ПРИСОЕДИНЯЯ, где присутствует подсказка.
Я сделал следующее без ошибок;
DBCC UPDATEUSAGE (0) WITH INFO_MESSAGES, COUNT_ROWS;
EXECUTE sp_updatestats 'resample';
DBCC CHECKDB (0) WITH ALL_ERRORMSGS, EXTENDED_LOGICAL_CHECKS;
Я в тупик ... любые идеи?
Вот UDF определения
ALTER FUNCTION dbo.Cases(@day date) RETURNS TABLE
WITH SCHEMABINDING
AS RETURN (
SELECT
CaseID -- other 42 columns ommitted
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY CaseID ORDER BY UpdateDate DESC, UpdateNumber DESC) AS RecordAge,
CaseID,
Action
FROM
dbo.CaseAudit
WHERE
convert(date,UpdateDate) <= @day
) AS History
WHERE
RecordAge = 1 -- only the most current record version
AND isnull(Action,'') != N'DEL' -- only include cases that have not been deleted
)
ALTER FUNCTION dbo.AwareDates(@day date) RETURNS TABLE
WITH SCHEMABINDING
AS RETURN (
WITH
History AS (
SELECT row_number() OVER (PARTITION BY CaseID, ContactID ORDER BY UpdateDate DESC, UpdateNumber DESC) AS RecordAge,
CaseID, InfoReceived, ReceiveDate, ResetClock, Action
FROM dbo.ContactLogAudit WITH (NOLOCK)
WHERE convert(date,UpdateDate) <= @day
),
Notes AS (
SELECT
CaseID,
convert(date,ReceiveDate,112) AS ReceiveDate,
ResetClock
FROM History
WHERE RecordAge = 1 -- only the most current record version
AND isnull(Action,'') != N'DEL' -- only include notes that have not been deleted
AND InfoReceived = N'Y' -- only include notes that have Info Rec'd checked
AND len(ReceiveDate) = 8 AND isnumeric(ReceiveDate) = 1 AND isdate(ReceiveDate) = 1 -- only include those with a valid aware date
),
Initials AS (
SELECT CaseID, min(ReceiveDate) AS ReceiveDate
FROM Notes
GROUP BY CaseID
),
Resets AS (
SELECT CaseID, max(ReceiveDate) AS ReceiveDate
FROM Notes
WHERE ResetClock = N'Y'
GROUP BY CaseID
)
SELECT
i.CaseID AS CaseID,
i.ReceiveDate AS InitialAwareDate, -- the oldest valid aware date value (must have AE Info Reveived checked and a received date)
coalesce(r.ReceiveDate,i.ReceiveDate) AS AwareDate -- either the newest valid aware date value with the Reset Clock checked, otherwise the initial aware date value
FROM Initials AS i
LEFT JOIN Resets AS r
ON i.CaseID = r.CaseID
);
Я также обнаружили, что если я уронить "С (NOLOCK)" таблицы намек, я получаю правильные результаты. Также, если добавить ссылку на соединение с AwareDates UTF или даже добавить COLLATE Latin1_General_BIN в отношении LEFT JOIN между Initials и Resets.
план запроса строки отсчетов - без намека присоединиться (пунктирная)
- Случаи {Фактическое: 25891, Оценка: 19,071.9}
- AwareDates {Действительные: 24,693, Оценено: 1,463.09}
- Инициалы {Фактические: 24,693, Оценочные: 1,463.09}
- Отдыхает {Фактический: 985, Оценено: 33,2671}
- AwareDates соответствует 8,108 строкам случаев в join'd множества результатов
Запрос план строки отсчетов - с присоединиться к подсказке (рабочему)
- Случаи {Фактические: 25,891, Оценка : 19,071.9}
- AwareDates {Действительные: 24,673, Оценочные: 1,837.67}
- Инициалы {Фактическое: 24673, Оценено: 1,837.67}
- Остатки {Актуально: 982, Предполагаемый: 42.6238}
- AwareDates соответствует 24,673 строк случаев в join'd множества результатов
я дополнительно сократился объем выпуска. Я могу;
SELECT * FROM AwareDate(@date);
и
SELECT * FROM AwareDate(@date) ORDER BY CaseID;
С различными подсчетов строк.
Можете ли вы поделиться определением своих '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' Самый большой красный флаг для меня - это то, что вы запрашиваете вывод функции, а не таблицы. – JNK
+1 для настоящей тайны. Могу сказать, что я никогда не пытался присоединиться к двум функциям раньше.Поскольку вы спрашиваете о плохом индексе, я предполагаю, что функции получают данные из таблиц. Можете ли вы запросить таблицы непосредственно, а не выполнять функции? Можете ли вы взглянуть? –
Я пробовал несколько других способов запроса данных, и если я помещаю вывод табличной функции в временную таблицу, а затем присоединяюсь к двум темповым таблицам без подсказки, он работает так, как ожидалось. Кроме того, если я (SELECT TOP 999999 * FROM AwareDate (@date) ORDER BY CaseID) AS a работает без подсказки. –