Медленный запрос при обновлении с использованием select count (*) - PullRequest
0 голосов
/ 07 сентября 2011

Мне нужно посчитать, сколько раз число из таблицы2 встречается между числом в диапазоне table2.a и table2.b

т.е. мы хотим знать, сколько раз у нас это: a

Я запустил следующий запрос:

UPDATE table2
 SET occurrence =  
       (SELECT COUNT(*) FROM table1 WHERE start BETWEEN table2.a AND table2.b);



table2 
ID   a   b    occurrence
1    1   10
2    1   20
3    1   25
4    2   30


table1 
ID start col1 col2 col3
1   1
2   7
3  10
4  21
5  25
6  27
7  30

table2 as

  • 3 указателя на a, b и вхождение
  • 1567 строк (поэтому мы выберем COUNT (*) поверх table2 1567 раз ..)
  • ID столбца как PK

table1 as

  • 1 индекс при старте
  • 42 000 000 строк
  • Начало столбца было "упорядочено по началу столбца"
  • ID столбец как PK

==> 2/3 времени заняло 2,5 часа. Мне нужно ускорить это ... какие-либо предложения? :)

Ответы [ 4 ]

1 голос
/ 08 сентября 2011

Используйте хранимую процедуру. Сохраните результат из COUNT в локальной переменной, а затем используйте его для запуска запроса UPDATE.

1 голос
/ 08 сентября 2011

Вы можете попытаться добавить столбец id в индекс таблицы 1:

CREATE INDEX start_index ON table1 (start,id);

и переписать запрос на

UPDATE table2
 SET occurrence =  
       (SELECT COUNT(id) FROM table1 WHERE start BETWEEN table2.a AND table2.b);

Это называется "индексом покрытия": http://www.simple -talk.com / sql / learn-sql-server / использование-покрытия-индексов-для-улучшения-запроса-производительности /

-> Весь запрос к таблице 1 может быть обработан через данные в индексе -> нет дополнительного поиска страницы для фактической записи.

0 голосов
/ 07 сентября 2011

Я сделаю это

// use one expensive join
create table tmp
select table2.id, count(*) as occurrence 
from table1
inner join table1
on table1.start between table2.a and table2.b
group by table1.id;

update table2, tmp
set table2.occurrence=tmp.occurrence 
where table2.id=tmp.id;
0 голосов
/ 07 сентября 2011

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

UPDATE table2
 SET occurrence =  
       (SELECT COUNT(1) FROM table1 WHERE start BETWEEN table2.a AND table2.b);
...