2015-03-12 3 views
3

В моем обновленном запросе ниже у меня есть два подзапроса. Оба они одинаковы, за исключением столбца, который он выбирает (ColumnA, ColumnB). Один подзапрос дает более 100 000 записей, из которых будет выбран первый ряд.SQL Performance tuning - Обновить запрос

Но есть проблема с производительностью, так как можно объединить два подзапроса в один запрос.

Как совместить это.

UPDATE TABLE1 SET 
LOWEST_RATE = (SELECT TOP 1 ColumnA from Table2 WHERE Table2.Currency = Table1.Currency), 
DIFF_RATE = (SELECT TOP 1 ColumnB from Table2 WHERE Table2.Currency = Table1.Currency) 
+2

Почему вы делаете top 1 без заказа? Вам не гарантируется требуемое значение. – Bobby

+0

Пожалуйста, объясните немного больше об объемах данных. Сколько строк (всего) для таблицы1? и сколько строк (всего) для таблицы2? Вы говорите, что для КАЖДОЙ строки в таблице 1 подзапрос будет сканировать 100 000 строк в таблице2. ["lakh" как термин не всегда понят, поэтому я использовал 100 000] –

+0

Какие индексы существуют в этих таблицах? можем ли мы получить DDL, включая индексы плюс некоторые примеры данных из каждой таблицы, пожалуйста. (небольшой образец в порядке) –

ответ

0

Используйте обновляемый КТР и row_number(), чтобы получить только одну строку для каждой валюты:

;with x as (
select Currency, ColumnA, ColumnB, 
row_number() over(partition by Currency order by ...) as rn 
from Table1 
), 
y as (
select t1.*, t2.* 
from Table1 t1 
join x t2 on t1.currency = t2.currency and t2.rn = 1 
) 
update y 
set 
lowest_rate = ColumnA, 
diff_rate = ColumnB 

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

0

может быть, вы можете сделать что-то вроде этого

UPDATE TABLE1 SET 
       LOWEST_RATE = (SELECT TOP 1 ColumnA), 
       DIFF_RATE = (SELECT TOP 1 ColumnB) 
from Table2 INNER JOIN Table1 
on Table2.Currency = Table1.Currency 
0

Если не ошибаюсь, ваш correlated subqueries можно преобразовать в INNER JOIN. Попробуй это.

UPDATE A 
SET LOWEST_RATE = B.columna, 
     DIFF_RATE = C.columnb 
FROM table1 A 
     INNER JOIN (SELECT Max(columna) ColumnA, 
          currency 
        FROM table2 
        GROUP BY currency) B 
       ON A.currency = B.currency 
     INNER JOIN (SELECT Max(columnb) ColumnB, 
          currency 
        FROM table2 
        GROUP BY currency) C 
       ON A.currency = C.currency 
0

Использование CROSS APPLY является эффективным способом борьбы с коррелированными подзапросами, которые выполняются в обновление через КТР.

;WITH cte 
    AS (
     SELECT 
      table1.lowest_rate 
      , table1.diff_rate 
      , ca1.lowest_one 
      , ca2.highest_one 
     FROM table1 
     CROSS APPLY (
       SELECT TOP (1) 
        ColumnA 
       FROM table2 
       WHERE table1.Currency = table2.Currency 
       ORDER BY 
        ColumnA ASC 
      ) ca1 (lowest_one) 
     CROSS APPLY (
       SELECT TOP (1) 
        ColumnB 
       FROM table2 
       WHERE table1.Currency = table2.Currency 
       ORDER BY 
        ColumnB DESC 
      ) ca2 (highest_one) 
     ) 
UPDATE cte 
SET 
    lowest_rate = lowest_one 
    , diff_rate = highest_one 
;