2014-01-24 3 views
0

У меня есть два сервера. Один мой, а другой - другой компании. На втором сервере я не могу создать какую-либо базу данных или добавлять какие-либо функции или хранить процедуры, но мне нужно вернуть информацию для перекрестного соединения с моей базой данных.связанный сервер с перекрестным соединением

, например,

select fieldA, fieldB from localTBL l 
left join linkedserver.remoteDB.dboremoteTBL r on l.ID = r.ID 

или

select fieldA, fieldB from linkedserver.remoteDB.dboremoteTBL r 
where r.ID in (select l.ID from localTBL l) 

Я сделал это, но выступление было очень ужасно.

Возможно ли это сделать с лучшей производительностью?

ответ

1

Для повышения производительности со связанными серверами используйте openquery. В противном случае сначала вы возвращаете все данные с удаленного сервера и затем применяете предложение where.

В вашей ситуации сначала запустите подзапрос и верните список значений в переменную. Затем используйте эту переменную в вашем openquery.

+0

В основном я согласен с тем, что с помощью OPENQUERY, но это не так черное и белое, как вы заставляете его звучать. Использование распределенного запроса (linkedserver.database.schema.table) ** может ** сначала вернуть все данные и создать копию в tempdb, если она сочтет это целесообразным, а затем применить фильтр. Этот ответ звучит так, как будто это всегда будет так. – GarethD

+0

Кроме того, распределенный запрос может использовать статистические данные на связанном сервере, поэтому, если предложение where означает, что будет возвращено не так много строк, он не будет создавать полную копию и будет соответствующим образом регулировать любые последующие взаимодействия (например, считают, что вложенное соединение цикла более эффективно, чем хеш-совпадение, потому что всего 50 строк). OPENQUERY не может этого сделать, и (AFAIK) всегда предполагает, что будет возвращено 10 000 строк. Это может привести к использованию менее неэффективного соединения с другими данными. – GarethD

0

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

Вот почему Linked Servers не используются очень сильно, даже в пределах одной компании: производительность обычно плохая. (Я никогда не видел Linked Server в отдельной компании и могу только посочувствовать!)

Если вы не можете обновить сетевую связь между вами, вы не можете делать запросы с связанного сервера.

Эта установка звучит как краткосрочное решение проблемы, которая требует быстрого исправления и которая длится дольше, чем ожидалось. Если вы можете получить бизнес-кейс для расходования средств на него, то возможны две альтернативы:

Самая дешевая альтернатива: это кэширование данных локально: есть фоновый сервис, который перетаскивает последнюю версию данных из таблиц Linked Server в набор в таблице в локальной базе данных, а затем выполните ваши запросы против локальных таблиц. Это зависит от того, насколько изменчивы удаленные данные и насколько актуальны ваши запросы. Форекс, если вы делаете такие вещи, как получение вчерашних данных о продажах, вы можете сделать ночную тягу. Если вам нужны более свежие данные, возможно, почасовая тяга. Иногда вы можете получать довольно придирчивые данные, и если структуры данных поддерживают его, то вытаскивают только данные, которые изменились с момента последнего натяжения: каждый из них тянет намного меньше и позволяет более частые, возможно.

Более дорогие, связанные с работой вашей и другой компании: перепроектировать ее так, чтобы другая компания подтолкнула вас к изменениям, как они есть, через службу WCF (или что-то), которую вы раскрываете. Это может затем обновить вашу локальную копию по мере поступления данных.

1

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

DECLARE @Id As int; 
SELECT @Id = 45; 

with cte (ID, fieldB) 
AS 
(
    SELECT ID, fieldB 
    FROM linkedserver.remoteDB.dboremoteTBL 
    WHERE ID = @Id 
) 

SELECT lt.fieldA, cte.fieldB 
FROM localTbl lt 
    INNER JOIN cte ON lt.ID = cte.ID 
ORDER BY lt.ID; 
Смежные вопросы