Как ускорить отклик сервера на запрос данных?

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

ArtDen
Сообщения: 53
Зарегистрирован: 25 ноя 2007, 10:54

Как ускорить отклик сервера на запрос данных?

Сообщение ArtDen » 05 дек 2007, 19:59

Ситуация такая. Приходиться выбирать большой объём данных (250 000 строк и более) из больших таблиц (> 64 столбцов). Из двух таблиц путём их перемножения выбирается данные по индексным полям. План запроса следующий:

Код: Выделить всё

PLAN JOIN (RECORDS ORDER RECORDS_ID_INDEX INDEX (RECORDS_TYPE_INDEX, RECORDS_RACE_INDEX), REC_VALUES INDEX (REC_VALUES_ID_INDEX))
Не устраивает скорость между запросом и приходим первой порцией данных с сервера. В этот период сервак долго шелестит винчестером практически без загрузки процессора. Если то-же самый запрос повторить сразу после прошлого запроса, то сервер откликается практически сразу. Но стоит сделать несколько запросов из разных участков таблицы, как время отклика опять увеличивается.
Я так понимаю, что это происходит из-за того, что всё время сервер не держит индексы в памяти, подгружая/выгружая их по мере необходимости. Можно как-то заставить сервер держать индексы в памяти всё время? Или хотя бы задать приоритет для индексов перед обычными данными, которые кешируются в памяти? И вообще, правильно ли я представляю проблему и дело вообще не в индексах, а в чём-то другом?

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 05 дек 2007, 20:14

Возможных причин слишком много, чтобы сказать "проблема тут".
Во-первых, ты не указал версию сервера.
Во-вторых, запроса.
Можно предположить так с ходу, что запрос слишком долго в порядке индекса идёт до собственно данных, занимается ненужной работой.
В общем, давай запрос.

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Re: Как ускорить отклик сервера на запрос данных?

Сообщение stix-s » 05 дек 2007, 20:23

ArtDen писал(а):Ситуация такая. Приходиться выбирать большой объём данных (250 000 строк и более) из больших таблиц (> 64 столбцов). Из двух таблиц путём их перемножения выбирается данные по индексным полям. План запроса следующий:

Код: Выделить всё

PLAN JOIN (RECORDS ORDER RECORDS_ID_INDEX INDEX (RECORDS_TYPE_INDEX, RECORDS_RACE_INDEX), REC_VALUES INDEX (REC_VALUES_ID_INDEX))
Не устраивает скорость между запросом и приходим первой порцией данных с сервера. В этот период сервак долго шелестит винчестером практически без загрузки процессора. Если то-же самый запрос повторить сразу после прошлого запроса, то сервер откликается практически сразу. Но стоит сделать несколько запросов из разных участков таблицы, как время отклика опять увеличивается.
Я так понимаю, что это происходит из-за того, что всё время сервер не держит индексы в памяти, подгружая/выгружая их по мере необходимости. Можно как-то заставить сервер держать индексы в памяти всё время? Или хотя бы задать приоритет для индексов перед обычными данными, которые кешируются в памяти? И вообще, правильно ли я представляю проблему и дело вообще не в индексах, а в чём-то другом?
в кэш поди кидает,навена и сортировка присутствует :)
, а кому из клиентов понадобилось поглядеть разом на 250 тыс строк?

ArtDen
Сообщения: 53
Зарегистрирован: 25 ноя 2007, 10:54

Сообщение ArtDen » 05 дек 2007, 20:38

WildSery писал(а):Во-первых, ты не указал версию сервера.
Извиняюсь. FB 2.0.3, WinXP SP2
WildSery писал(а):Во-вторых, запроса.
Запрос создаётся программно, но сейчас попробую воспроизвести. Вот частный случай запроса (просьба не смеяться :) ):

Код: Выделить всё

SELECT records.id_mk, records.race, records.rec_time, records.time_offset, records.depth_z, records.depth_cur, records.depth_lag, records.operation , 
  rec_values.p01, rec_values.v01, 
  rec_values.p02, rec_values.v02, 
  rec_values.p03, rec_values.v03, 
  rec_values.p04, rec_values.v04, 
  ... ,
  rec_values.p32, rec_values.v32 

FROM records, rec_values 

WHERE records.id_mk=rec_values.id_records AND records.race IN (52,53,141 ) AND records.rec_type=1 

ORDER BY records.id_mk;
В принципе, ORDER BY records.id_mk лишнее, т.к. записи в таблице гарантировано располагаются в порядке возрастания records.id_mk, но если убрать ORDER BY records.id_mk, то это не сильно меняет ситуацию.

ArtDen
Сообщения: 53
Зарегистрирован: 25 ноя 2007, 10:54

Re: Как ускорить отклик сервера на запрос данных?

Сообщение ArtDen » 05 дек 2007, 20:41

stix-s писал(а):а кому из клиентов понадобилось поглядеть разом на 250 тыс строк?
Эти данные после запроса визуализируются в виде графиков кривых на экране. Так что количество данных - тут оправдано

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 05 дек 2007, 21:55

Не включая мозг: для начала грохнуть или просто заблокировать в запросе индекс по RECORDS_TYPE_INDEX. Там к бабке не ходи пять с половиною значений на все двестипсят тыщ записей. Дальше смотреть статистику индекса RECORDS_RACE_INDEX, может и его фтопку.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 05 дек 2007, 21:59

сходу

Код: Выделить всё

AND records.race+0 IN ...

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 05 дек 2007, 22:04

kdv писал(а):сходу

Код: Выделить всё

AND records.race+0 IN ...
Вроде Влад с Димой били себя пяткой в грудь, что IN в двойке не настолько ресурсоёмок, как раньше. Скока там рас, правда, трудно сказать, в отличие от типов :) Вроде больше 100, должно быть ничо, ежели распределены равномерно. Вот если узким пиком, тады да, только внутри него индекс полезен.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 05 дек 2007, 22:39

раньше для in использовалось столько "индексов", сколько было значений в перечислении. потом в YA и теперь в FB 2 для этого используется только один индекс. Но сканов индекса, как я понимаю, сколько было столько и осталось. Так что, небольшая экономия памяти и скорости. Проявляется сильно, на мой взгляд, когда значений в in указано поболе 4-5, ну и от количества разных значений в индексе тоже зависит.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 05 дек 2007, 23:34

Я бы первым делом убил индекс в ORDER BY. Он полезен, только если выбирается мало записей

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 06 дек 2007, 00:54

ну так видишь, ему не нравится что первая порция медленно выдается. а при сортировке если там дофига записей первая порция точно будет с задержкой.

ArtDen
Сообщения: 53
Зарегистрирован: 25 ноя 2007, 10:54

Сообщение ArtDen » 06 дек 2007, 09:44

Merlin писал(а):Дальше смотреть статистику индекса RECORDS_RACE_INDEX, может и его фтопку.
А насколько маленькой должна быть статистика, чтобы убрать индекс?

ArtDen
Сообщения: 53
Зарегистрирован: 25 ноя 2007, 10:54

Сообщение ArtDen » 06 дек 2007, 09:45

kdv писал(а):сходу

Код: Выделить всё

AND records.race+0 IN ...
А что это может дать?

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 06 дек 2007, 10:12

ArtDen писал(а):
kdv писал(а):сходу

Код: Выделить всё

AND records.race+0 IN ...
А что это может дать?
отмену использования индекса по данному полю
ты что-либо пробовал?

ArtDen
Сообщения: 53
Зарегистрирован: 25 ноя 2007, 10:54

Сообщение ArtDen » 06 дек 2007, 10:24

hvlad писал(а):Я бы первым делом убил индекс в ORDER BY. Он полезен, только если выбирается мало записей
Хм... Выяснилось, что мой индекс для records.id_mk полностью дублирует индекс, созданный самим FB для основного ключа. Задизаблил я свой индекс и время отклика сразу уменьшилось. Правда, после этого я сделал для него енабле, а время отклика осталось таким-же маленьким. Короче, чудеса :)

ArtDen
Сообщения: 53
Зарегистрирован: 25 ноя 2007, 10:54

Сообщение ArtDen » 06 дек 2007, 10:32

stix-s писал(а):отмену использования индекса по данному полю
ты что-либо пробовал?
Попробовал records.race+0 IN . До сих пор жду ответа от сервера :) Другими словами время отклика увеличилось на несколько порядков

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 06 дек 2007, 12:33

Правда, после этого я сделал для него енабле
нахрена?
Попробовал records.race+0 IN . До сих пор жду ответа от сервера
тогда ты как-нибудь сам разбирайся. прочитай про методы доступа, про оптимизацию запросов, и т.п.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 06 дек 2007, 12:39

ArtDen писал(а):Правда, после этого я сделал для него енабле, а время отклика осталось таким-же маленьким. Короче, чудеса :)
Посмотри ещё раз план. Если там по-другому стало, значит, пересчиталась статистика индекса.
И вообще, обнови статистику индексов.

ArtDen
Сообщения: 53
Зарегистрирован: 25 ноя 2007, 10:54

Сообщение ArtDen » 06 дек 2007, 13:42

kdv писал(а):нахрена?
Чтобы убедиться, что дело было именно в этом индексе. Сейчас я его вообще удалил.
kdv писал(а):тогда ты как-нибудь сам разбирайся. прочитай про методы доступа, про оптимизацию запросов, и т.п.
Не совсем понял твой ответ. Я сказал, что с запросом records.race+0 IN работает гораздо дольше, чем с records.race IN, что подтверждает, что индекс по records.race необходим. Или я что-то не понимаю?
Последний раз редактировалось ArtDen 06 дек 2007, 14:03, всего редактировалось 1 раз.

ArtDen
Сообщения: 53
Зарегистрирован: 25 ноя 2007, 10:54

Сообщение ArtDen » 06 дек 2007, 14:01

WildSery писал(а):Посмотри ещё раз план. Если там по-другому стало, значит, пересчиталась статистика индекса.
План стал таким:

Код: Выделить всё

PLAN JOIN (RECORDS ORDER RDB$PRIMARY2 INDEX (RECORDS_RACE_INDEX, RECORDS_TYPE_INDEX), REC_VALUES INDEX (REC_VALUES_ID_INDEX))
Т.е. поменялись местами RECORDS_RACE_INDEX и RECORDS_TYPE_INDEX

Ответить