Как я могу сначала отсортировать действия моих друзей и сохранить хорошую производительность? - PullRequest
2 голосов
/ 02 мая 2019

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

Если мы наполним таблицу «Деятельности» миллионами записей, мы все равно сможем использовать индекс и ускорить поиск действий.Однако это происходит медленно, когда я хочу упорядочить результат по действиям друзей в верхней части.

Подумайте, когда поиск из таблицы «Действия» возвращает 1000 строк, а затем нам нужно отсканировать таблицу друзей и сопоставить с 1000строк из соответствующей таблицы в разделе «Деятельности».

Есть ли у вас какие-либо предложения о том, как переписать или повторно смоделировать эту базу данных / запрос, чтобы она была быстрой?Или проблема должна решаться по-другому?Я ищу решение, стабильное по скорости даже при росте данных.

declare @Activities as table 
(
    UserId int, ActivityName nvarchar(50), AccountName nvarchar(50), ActivityDate DateTime, Likes int
    INDEX IX NONCLUSTERED (AccountName,ActivityDate,Likes,UserId,ActivityName) 
)
declare @Friends as table 
(
    UserId int, FriendId int
    INDEX IX CLUSTERED (UserId, FriendId)
)

insert into @Activities values (1, 'Activity 1', 'John Doe', '2019-01-01', 10) 
insert into @Activities values (2, 'Activity 2', 'Max Gordon', '2019-02-01', 100)
insert into @Activities values (1, 'Activity 3', 'John Doe', '2019-03-01', 0)
insert into @Activities values (3, 'Activity 4', 'John Roe', '2019-08-01', 40)

insert into @Friends values (1,2) -- John is friend with max
insert into @Friends values (2,1) -- Max is friend with John
insert into @Friends values (1,3) -- John Doe is friend with John Roe

declare @UserId int = 2

select top 10
    a.ActivityName, a.AccountName, a.Likes, case when f.FriendId is null then 0 else 1 end as IsFriend
from 
    @Activities a
    left join @Friends f on f.UserId = @UserId and f.FriendId = a.UserId
where 
    a.AccountName like 'j%'
order by 
    case when f.FriendId is null then 0 else 1 end desc, 
    a.Likes desc,  
    case when a.ActivityDate > getdate() then 0 else 1 end,
    a.ActivityDate

Ответы [ 2 ]

0 голосов
/ 02 мая 2019

Возможно, коррелированный подзапрос может быть более эффективным, чем оператор Left Join + Case

select top 10
    a.ActivityName, a.AccountName, a.Likes, IsFriend
from 
    @Activities a
    outer apply (select 1 as isFriend FROM @Friends f WHERE f.UserId = @UserId and f.FriendId = a.UserId) f
where 
    a.AccountName like 'j%'
order by 
    isFriend desc, 
    a.Likes desc,  
    case when a.ActivityDate > getdate() then 0 else 1 end,
    a.ActivityDate
0 голосов
/ 02 мая 2019

Попробуйте что-то вроде этого:

SELECT a.*, COUNT(f.*) AS FriendCount
FROM Activities a
LEFT OUTER JOIN Friends f ON f.FriendId = a.UserId AND f.UserId = @UserId
GROUP BY a.*
ORDER BY SIGN(COUNT(f.*)) DESC, a.LIKES DESC, a.ActivityDate DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...