Долгий запрос count
От: Kvazimodo75  
Дата: 20.04.16 15:50
Оценка:
Есть таблица в которой довольно часто меняются данные (вставка, обновление, удаление).

И тут понадобилось сделать count(a) where person_id in ....

в результате время выполнения запроса — 7 минут

Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)
Re: Долгий запрос count
От: Milena США  
Дата: 20.04.16 15:55
Оценка:
Здравствуйте, Kvazimodo75, Вы писали:

K>Есть таблица в которой довольно часто меняются данные (вставка, обновление, удаление).

K>И тут понадобилось сделать count(a) where person_id in ....
K>в результате время выполнения запроса — 7 минут
K>Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)

1) Если нужно просто посчитать количество строк, где person_id = ..., то лучше считать count(person_id)
2) Covering index (person_id, a)
3) Index on person_id include (a)
Re: Долгий запрос count
От: Softwarer http://softwarer.ru
Дата: 20.04.16 17:00
Оценка:
Здравствуйте, Kvazimodo75, Вы писали:

K>в результате время выполнения запроса — 7 минут


Для начала следует разобраться, на что СУБД тратит эти семь минут. Для этого есть всякие разные инструменты, описанные в performance tuning guide тщательно скрываемого Вами сервера.

K>Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)


Придумать можно много, но как бы ежу понятно, что в случаях "в таблице 1.000.000.000 записей" и "в таблице 100 записей" правильные действия будут немного разными.
Re: Долгий запрос count
От: vsb Казахстан  
Дата: 20.04.16 17:06
Оценка:
Здравствуйте, Kvazimodo75, Вы писали:

K>Есть таблица в которой довольно часто меняются данные (вставка, обновление, удаление).


K>И тут понадобилось сделать count(a) where person_id in ....


K>в результате время выполнения запроса — 7 минут


K>Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)


1. Не делать count(*). Обычно это реально никому не надо.

2. Вести статистику в отдельной таблице, может быть даже не в СУБД, например при старте сервера считать число строк и потом хранить это значение в оперативной памяти сервера (если у нас не кластер). В связи с транзакциями, откатами и тд значение может быть неточным, но для миллионов обычно интересен примерный порядок, а не точное значение.

2.1. Использовать служебные данные из статистики БД.

По факту count(*) это тяжёлая операция, если её делать корректно и таблица большая и от этого никуда не деться.
Re: Долгий запрос count
От: londinium Украина  
Дата: 20.04.16 17:43
Оценка:
Здравствуйте, Kvazimodo75, Вы писали:

K>Есть таблица в которой довольно часто меняются данные (вставка, обновление, удаление).


K>И тут понадобилось сделать count(a) where person_id in ....


K>в результате время выполнения запроса — 7 минут


K>Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)

select count(a)from tablea with(nolock)
where person_id in
Re: Долгий запрос count
От: Dym On Россия  
Дата: 20.04.16 21:01
Оценка:
K>И тут понадобилось сделать count(a) where person_id in ....
А после in что?
Счастье — это Glück!
Re: Долгий запрос count
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.04.16 21:11
Оценка:
Здравствуйте, Kvazimodo75, Вы писали:

K>Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)


План в студию
Re: Долгий запрос count
От: Sammo Россия  
Дата: 21.04.16 03:55
Оценка:
K>Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)
Кроме вышесказанного — еще раз посмотреть, что там в in. В некоторых случаях эффективнее exists. Иногда (если там подзапрос) внутреннее соединение.
Может слишком большой список пытаетесь запихнуть в in.
Re: Долгий запрос count
От: Иль  
Дата: 21.04.16 05:24
Оценка: +3
Здравствуйте, Kvazimodo75, Вы писали:

K>Есть таблица в которой довольно часто меняются данные (вставка, обновление, удаление).

...
K>Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)

Потрясающе. Люди уже дают советы, но при этом что за запрос, или что за СУБД хотя бы — никто даже не уточнил
Re: Долгий запрос count
От: wildwind Россия  
Дата: 21.04.16 07:16
Оценка:
Здравствуйте, Kvazimodo75, Вы писали:

K>Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)


Проанализировать план и статистику выполнения запроса и найти узкое место. Для начала.
Re: Долгий запрос count
От: Kvazimodo75  
Дата: 21.04.16 07:45
Оценка:
Здравствуйте, Kvazimodo75, Вы писали:

K>Есть таблица в которой довольно часто меняются данные (вставка, обновление, удаление).


K>И тут понадобилось сделать count(a) where person_id in ....


K>в результате время выполнения запроса — 7 минут


K>Что можно придумать, чтобы работало быстро? (приемлемо секунд 30)


Сервер MS SQL 2014.


План запроса:
http://files.rsdn.ru/39889/plan_count.jpg

Количество записей исчисляется десятками тысяч — вроде как не много совсем.


Примерный результат не допустим.
Re[2]: Долгий запрос count
От: Kvazimodo75  
Дата: 21.04.16 07:46
Оценка:
Здравствуйте, vsb, Вы писали:


vsb>1. Не делать count(*). Обычно это реально никому не надо.


Где Вы видели звездочку?

vsb>2. Вести статистику в отдельной таблице, может быть даже не в СУБД, например при старте сервера считать число строк и потом хранить это значение в оперативной памяти сервера (если у нас не кластер). В связи с транзакциями, откатами и тд значение может быть неточным, но для миллионов обычно интересен примерный порядок, а не точное значение.


Нужно точное значение


vsb>2.1. Использовать служебные данные из статистики БД.
Re[2]: Долгий запрос count
От: Kvazimodo75  
Дата: 21.04.16 07:48
Оценка:
Здравствуйте, Dym On, Вы писали:

K>>И тут понадобилось сделать count(a) where person_id in ....

DO>А после in что?

Быстрый селект.
Без count тот же запрос выполняется за 0-1 секунду.
Re[3]: Долгий запрос count
От: _ABC_  
Дата: 21.04.16 08:50
Оценка:
Здравствуйте, Kvazimodo75, Вы писали:

K>Быстрый селект.

K>Без count тот же запрос выполняется за 0-1 секунду.
Делаю предположение, что count(cpl1.id) — это и есть count(a)?
Идет скан всей таблицы для получения cpl1.id и последующий nested join.
Одним из возможных решений является создание индекса, который подсказывает план.

Скачайте SQL Sentry Plan Explorer и прогоните запрос там. У него есть функция анонимизации
плана в бесплатной версии. После анонимизации можно без особой опаски выложить полный план
в виде отдельного файла, а не скриншота.
Re[2]: Долгий запрос count
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.04.16 09:47
Оценка: +1
Здравствуйте, Kvazimodo75, Вы писали:
K>Сервер MS SQL 2014.
K>План запроса:

1. План — от какого-то совсем другого запроса. В кроме count() есть много всего прочего, что влияет на стоимость.
2. Удивительным образом, на плане прямо написан совет, как ускорить ваш запрос.
Вы пробовали этот совет применить?

K>Количество записей исчисляется десятками тысяч — вроде как не много совсем.



K>Примерный результат не допустим.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 21.04.2016 9:49 Sinclair . Предыдущая версия . Еще …
Отредактировано 21.04.2016 9:48 Sinclair . Предыдущая версия .
Re[3]: Долгий запрос count
От: Dym On Россия  
Дата: 21.04.16 09:51
Оценка:
S>1. План — от какого-то совсем другого запроса. В нём вообще нет count(). Зато есть много всего
Да не, есть у него там ближе к правому краю картинки: count(cpl1.cpid)

PS Но давать план запроса в таком виде это форменное издевательство.
Счастье — это Glück!
Re[3]: Долгий запрос count
От: Kvazimodo75  
Дата: 21.04.16 10:56
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>1. План — от какого-то совсем другого запроса. В кроме count() есть много всего прочего, что влияет на стоимость.

S>2. Удивительным образом, на плане прямо написан совет, как ускорить ваш запрос.
S>Вы пробовали этот совет применить?

Данные в этой таблице постоянно обновляются, поэтому я не добавляю индексы в неё специально.



Решил тем, что результат count удивительным образом совпадает с порциями изменяемых данных, поэтому подсчитывается триггером и пишется в отдельную таблицу.

Исходный запрос изменён на left outer join с этой отдельной таблицей.
Re[4]: Долгий запрос count
От: Alex.Che  
Дата: 21.04.16 11:04
Оценка: +1
> Данные в этой таблице постоянно обновляются, поэтому я не добавляю индексы в неё специально.

Очень оригинальное решение.
Какова была первопричина принятия оного?
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Долгий запрос count
От: Milena США  
Дата: 21.04.16 14:39
Оценка: 1 (1)
Здравствуйте, Kvazimodo75, Вы писали:

K>Здравствуйте, Sinclair, Вы писали:


S>>1. План — от какого-то совсем другого запроса. В кроме count() есть много всего прочего, что влияет на стоимость.

S>>2. Удивительным образом, на плане прямо написан совет, как ускорить ваш запрос.
S>>Вы пробовали этот совет применить?

K>Данные в этой таблице постоянно обновляются, поэтому я не добавляю индексы в неё специально.


Ну знаете, тогда не стоит жаловаться. У вас идет сканирование таблицы (тупой перебор строки за строкой), потому что индексов нет. И как написал SQL Server, запрос можно улучшить в разы, добавив его.
Как по-вашему работают высоконагруженные системы с миллиардами записей — все часами ждут ответа? Думаете, там тоже без индексов совсем, потому что вставки по 1000 транзакций в минуту? Почитайте про FILLFACTOR, чтобы улучшить понимание того, что можно сбалансировать индексы, чтобы они нормально работали и на вставку, и на чтение.
Re[4]: Долгий запрос count
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.04.16 16:14
Оценка: 1 (1)
Здравствуйте, Kvazimodo75, Вы писали:

K>Данные в этой таблице постоянно обновляются, поэтому я не добавляю индексы в неё специально.

Ну, я бы всё таки рискнул и посмотрел, насколько это ухудшит производительность вставки.


K>Решил тем, что результат count удивительным образом совпадает с порциями изменяемых данных, поэтому подсчитывается триггером и пишется в отдельную таблицу.

Вы и вправду думаете, что триггер с записью в отдельную таблицу будет значительно быстрее, чем обновление индекса? Почему?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.