Мені здається, що where
пункт у запиті задає питання, і є причиною низьких оцінок, навіть якщо OPTION(RECOMPILE)
він використовується.
Я створив кілька тестових даних, і врешті-решт придумав два рішення, зберігаючи ID
поле з resources
будь-якої змінної (якщо вона завжди унікальна), або таблиці з тимчасовою таблицею, якщо у нас може бути більше одного ID
.
Базові записи тестів
SET NOCOUNT ON
DECLARE @i int= 1;
WHILE @i <= 10000
BEGIN
INSERT INTO [dbo].[Settings]([resourceId],[typeID],remark)
VALUES(@i,@i,'KEPT THESE VALUES OUT BECAUSE IT WOULD CLUTTER THE EXAMPLES, VALUES OVER 8000 Chars entered here'); -- 23254 character length on each value
INSERT INTO [dbo].[Resources](resourceUID)
VALUES(@i);
SET @i += 1;
END
Вставте значення "Шукати", щоб дійти до того ж приблизного набору результатів, що і ОП (1300 записів)
INSERT INTO [dbo].[Settings]([resourceId],[typeID],remark)
VALUES(38,38,'KEPT THESE VALUES OUT BECAUSE IT WOULD CLUTTER THE EXAMPLES, VALUES OVER 8000 Chars entered here')
GO 1300
Змініть компакт-дані та оновити статистику відповідно до ОП
ALTER DATABASE StackOverflow SET COMPATIBILITY_LEVEL = 120;
UPDATE STATISTICS settings WITH FULLSCAN;
UPDATE STATISTICS resources WITH FULLSCAN;
Оригінальний запит
exec sp_executesql N'
select r.id
FROM Resources r
inner join Settings on resourceid=r.id
where resourceUID=@UID
ORDER BY typeID',
N'@UID int',
@UID=38
Мої оцінки ще гірші : один розрахунковий ряд, тоді як 1300 повертаються. І як заявлено в ОП, не має значення, якщо я додаюOPTION(RECOMPILE)
Важливе, що слід зазначити, це те, що коли ми позбуємось пункту де, оцінки є на 100% правильними, що очікується, оскільки ми використовуємо всі дані в обох таблицях.
Я змусив індекси просто переконатися, що ми використовуємо ті самі, що і в попередньому запиті, щоб довести точку
exec sp_executesql N'
select r.id,remark
FROM Resources r with(index([IX_UID]))
inner join Settings WITH(INDEX([IX_Test]))
on resourceid=r.id
ORDER BY typeID',
N'@UID int',
@UID=38
Як і очікувалося, хороші оцінки.
Отже, що ми могли б змінити, щоб отримати кращі оцінки, але все ж шукати свої цінності?
ЯКЩО @UID унікальний, як у прикладі OP дано, ми могли б поставити сингл, id
який повернувся з resources
змінної, а потім шукати цю змінну за допомогою OPTION (RECOMPILE)
DECLARE @UID int =38 , @RID int;
SELECT @RID=r.id from
Resources r where resourceUID = @UID;
SELECT @uid, remark
from Settings
where resourceId = @uid
Order by typeID
OPTION(RECOMPILE);
Що дає 100% точні оцінки
Але що робити, якщо в ресурсах є кілька ресурсів UID?
додати деякі дані тесту
INSERT INTO Resources(ResourceUID)
VALUES (38);
go 50
Це можна вирішити за допомогою темп-таблиці
CREATE TABLE #RID (id int)
DECLARE @UID int =38
INSERT INTO #RID
SELECT r.id
from
Resources r where resourceUID = @UID
SELECT @uid, remark
from Settings s
INNER JOIN #RID r
ON r.id =s.resourceId
Order by typeID
OPTION(RECOMPILE)
DROP TABLE #RID
Знову з точними оцінками .
Це було зроблено за допомогою мого власного набору даних, YMMV.
Написано з sp_executesql
Зі змінною
exec sp_executesql N'
DECLARE @RID int;
SELECT @RID=r.id from
Resources r where resourceUID = @UID;
SELECT @uid, remark
from Settings
where resourceId = @uid
Order by typeID
OPTION(RECOMPILE);',
N'@UID int',
@UID=38
З темп-таблицею
exec sp_executesql N'
CREATE TABLE #RID (id int)
INSERT INTO #RID
SELECT r.id
from
Resources r where resourceUID = @UID
SELECT @uid, remark
from Settings s
INNER JOIN #RID r
ON r.id =s.resourceId
Order by typeID
OPTION(RECOMPILE)
DROP TABLE #RID',
N'@UID int',
@UID=38
Все-таки 100% правильні оцінки на моєму тесті
select r.id, LEFT(remark, 512)
(або будь-яка розумна довжина підрядки).