Ограничение времени выполнения запроса
Ограничение времени выполнения запроса
Существует ли у файрбирд (1.5.2) возможность ограничения времени выполнения запроса? Я не нашел нормального способа прервать запрос (только выборка данных, не обновление), если его выполнение заняло неадекватно большоен время.
Я знаю про то, что правильное решение - это не делать непредсказуемых запросов, строить индексы (они есть), обновлять статистику (она обвновляется), поставить вторую версию FB, который получше относится к сложным запросам (не могу сделать быстро) и т.д., но очень хочется иметь средство экстренного прерывания запроса. Работаю через ODBC.
Я знаю про то, что правильное решение - это не делать непредсказуемых запросов, строить индексы (они есть), обновлять статистику (она обвновляется), поставить вторую версию FB, который получше относится к сложным запросам (не могу сделать быстро) и т.д., но очень хочется иметь средство экстренного прерывания запроса. Работаю через ODBC.
в Firebird - пока нет. Кстати, IB 7.x тоже не всякие запросы может терминировать, как выяснилось.
вот и нет. для отчетных запросов самое правильное - построение промежуточных агрегатов. То есть, чтобы в системе просто не существовало запросов, которые могут выполняться, скажем, больше 3-5 минут (абстрактно).Я знаю про то, что правильное решение - это не делать непредсказуемых запросов, строить индексы...
-
- Заслуженный разработчик
- Сообщения: 1436
- Зарегистрирован: 15 сен 2005, 09:05
Да уж ... Ничего не скажешь - обломали.
Тогда попрошу помощи у зала. На чем зависаем?
таблица 1:
первичный ключ1 integer,
значение11, значение12, значение13 - integer
таблица 2:
первичный ключ2 integer,
значение21, значение22, значение23 - integer
таблица 12
пары ключ1, ключ2
(на самом деле это таблица людей, адресов и связей, причем имена, названия улиц и городов - словарные значения)
на входе запрос, в котором явно не указано, какое из слов - имя или улица, все это определяется по словарю и динамически строятся запросы,в зависимости от типа слов. Неоднозначность разрешается добавлением альтернатив через or, если одно и то же слово может быть и фамилией и отчеством, например
(значение12=123 or значение13=123) and значение11=456
если мы ищем только по первой таблице, или более сложно, через промежуточнуютаблицу, если указано условия, относящееся и к человеку, и к адрему.
Имеются независимые индексы по каждому из полей всех трех таблиц и объединенный индекс по обоим полям таблицы связей
Все это работает отлично и быстро, до ... неудачного расположения звезд на небе. На каком-то сочетании значений запрос, который работал до того быстро, начинает срашно тормозить (десятки секунд). Смена значений меняет план запроса (меняютися местами таблица1 и 2) и все начинает лелать. Однако непохоже, что дело в неудачном плане - в любом случае мы имеем поиск по индексам, а не natural.
Аналогичная ситуация - с запросами на поиск по ключевым словам. Есть таблица данных (первичный ключ) и таблица ключевых слов к данным, где указана пара: ключ из тьаблицы1 (integer), ключевое слово(integer)
в зависимости от количества ключевых слов в поиске строятся запросы типа
select kw1.link from keywords kw1,keywords kw2,keywords kw3 where kw1.link=kw2.link and kw1.link=kw3.link and kw1.word=123 and kw2.word=234 and kw3.word=456
тоже работает - супер, но иногда тормозит!
Тогда попрошу помощи у зала. На чем зависаем?
таблица 1:
первичный ключ1 integer,
значение11, значение12, значение13 - integer
таблица 2:
первичный ключ2 integer,
значение21, значение22, значение23 - integer
таблица 12
пары ключ1, ключ2
(на самом деле это таблица людей, адресов и связей, причем имена, названия улиц и городов - словарные значения)
на входе запрос, в котором явно не указано, какое из слов - имя или улица, все это определяется по словарю и динамически строятся запросы,в зависимости от типа слов. Неоднозначность разрешается добавлением альтернатив через or, если одно и то же слово может быть и фамилией и отчеством, например
(значение12=123 or значение13=123) and значение11=456
если мы ищем только по первой таблице, или более сложно, через промежуточнуютаблицу, если указано условия, относящееся и к человеку, и к адрему.
Имеются независимые индексы по каждому из полей всех трех таблиц и объединенный индекс по обоим полям таблицы связей
Все это работает отлично и быстро, до ... неудачного расположения звезд на небе. На каком-то сочетании значений запрос, который работал до того быстро, начинает срашно тормозить (десятки секунд). Смена значений меняет план запроса (меняютися местами таблица1 и 2) и все начинает лелать. Однако непохоже, что дело в неудачном плане - в любом случае мы имеем поиск по индексам, а не natural.
Аналогичная ситуация - с запросами на поиск по ключевым словам. Есть таблица данных (первичный ключ) и таблица ключевых слов к данным, где указана пара: ключ из тьаблицы1 (integer), ключевое слово(integer)
в зависимости от количества ключевых слов в поиске строятся запросы типа
select kw1.link from keywords kw1,keywords kw2,keywords kw3 where kw1.link=kw2.link and kw1.link=kw3.link and kw1.word=123 and kw2.word=234 and kw3.word=456
тоже работает - супер, но иногда тормозит!
А ты их статистику смотрел?pticelov писал(а): Имеются независимые индексы по каждому из полей всех трех таблиц
Именно в нём. а) индексный поиск не всегда лучше натурального б) а ты статистику используемых в том и другом случае индексов смотрел?pticelov писал(а): Смена значений меняет план запроса (меняютися местами таблица1 и 2) и все начинает лелать. Однако непохоже, что дело в неудачном плане - в любом случае мы имеем поиск по индексам, а не natural.
В общем прибей порядок таблиц гвоздиком. Лучше через +0, не получится - явным планом. А ещё лучше посмотреть статистику индексов и плохие перебить к едрене фене, может всё само и устаканится.
Смотрел, пересобирал. Вроде бы ничего ужасного.Merlin писал(а):А ты их статистику смотрел?pticelov писал(а): Имеются независимые индексы по каждому из полей всех трех таблиц
Там табличка на десятки миллионов записей. Какой-такой натуралMerlin писал(а):Именно в нём. а) индексный поиск не всегда лучше натурального б) а ты статистику используемых в том и другом случае индексов смотрел?pticelov писал(а): Смена значений меняет план запроса (меняютися местами таблица1 и 2) и все начинает лелать. Однако непохоже, что дело в неудачном плане - в любом случае мы имеем поиск по индексам, а не natural.
В общем прибей порядок таблиц гвоздиком. Лучше через +0, не получится - явным планом. А ещё лучше посмотреть статистику индексов и плохие перебить к едрене фене, может всё само и устаканится.

Перебить - это set statistics?
+0 - это что? Что-то я такого не встречал в документации. Сейчас окажетс ябанальность очевиднаяч

Кстати, в каком случае стоит отказаться от неуникальных индексов? Что-то меня смущает один из них (город), там количество значений (на десятки миллинов записей) очень ограничено (сотни, в лучшем случае - тысячи), причем, как и положено, на пару-тройку "главных" значений приходится подавляющее число записей.
Я наверное туплю.
есть запрос такой:
select ... from tbl1,tnl2,tbl21 where tbl1.link=tbl21.key1 and tbl2.link=tbl21.key2 and tbl1.val1=123 and tbl2.val2=456
есть индексы по всем упомянутым полям, у tbl21 - еще и индекс по паре полей (key1,key2)
почему при смене плана на симметричный начинаются тормоза - мне непонятно.
А что такое +0?
есть запрос такой:
select ... from tbl1,tnl2,tbl21 where tbl1.link=tbl21.key1 and tbl2.link=tbl21.key2 and tbl1.val1=123 and tbl2.val2=456
есть индексы по всем упомянутым полям, у tbl21 - еще и индекс по паре полей (key1,key2)
почему при смене плана на симметричный начинаются тормоза - мне непонятно.
А что такое +0?
Потому что размеры таблиц или даже просто количества записей, подпадающих под условия объединения, разные. И какую перебирать первой и по какому индексу - важно. А +0 - это обыгрывание того, что индекс к выражению не применяется. Например, напишешь tbl1.link=tbl21.key1+0 и индекс по key1 на tbl21 использоваться не будет, будет использоваться индекс по link на tbl1, как бы ты ни крутил параметры. То есть, этим можно управлять последовательностью перебора таблиц и не давать оптимизатору пытаться пользовать неподходящий для данного конкретного запроса индекс, хотя для другого запроса этот индекс хорош.
Я это понимаю, но это не объясняет уход сервера "в себя" на 20 минут на запросе типа
select ... from tbl1,tbl2,tbl21 where tbl1.ke1=... and tbl1.key2=... and tbl1.link=tbl21.key1 and tbl2.link=tbl21.key2 and tbl2.key5=...
"хорошее выполнеине" - доли секунды
"плохое" - десятки секунд.
Но улет на 20 минут я не могу объяснить инкак
Вот сейчас занимается чем-тос воим уже больше 20 минут. 100% загрузка процессора.
select ... from tbl1,tbl2,tbl21 where tbl1.ke1=... and tbl1.key2=... and tbl1.link=tbl21.key1 and tbl2.link=tbl21.key2 and tbl2.key5=...
"хорошее выполнеине" - доли секунды
"плохое" - десятки секунд.
Но улет на 20 минут я не могу объяснить инкак

не надо писать ерунду. Скорость выполнения запроса зависит от методов доступа, используемых сервером в конкретном случае. А методы доступа выбираются по типу запроса - сортировка, группировка, поиск по индексу, наличие индексов, и т.п."хорошее выполнеине" - доли секунды
Если ты запросом задаешь серверу отсортировать миллионов 5 записей, то он никак это за "доли секунды" выполнить не может.
это ты так запросы пишешь.Но улет на 20 минут я не могу объяснить инкак
Судя по всему, раз ты план не привел и не понял объяснения Merlin-а, тебе пока стоит пенять именно на себя, а не на сервер.
А может не наезжать, а прочитать, что тебе пишут. Я же написал, что за запрос и метод доступа. Поиск всегда по индексу, сортировка отсуствует. Именно поэтому нормальное время выполнения - доли секунды, при некоторых значениях - секунды (тут как раз "объяснение Мерлина"), иногда - десятки минут. На запросе таком:
select person.link,person.fname,person.pname,person.sname,person.birthday from person_1 person,address_1 address,person2addr_1 p2a where person.fname=450 and person.pname=344 and person.sname=71921 and person.birthday between 18800101 and 19671231 and p2a.person=person.link and p2a.addr=address.link and address.street in (39346)
план
PLAN JOIN (ADDRESS INDEX (ADDRESS_STREET_1),PERSON INDEX (PERSON1_1,PERSON_BIRTHDAY_1),P2A INDEX (PERSON2ADDR_1_1))
индексы:
person1_1 - по полям fname,sname,pname
PERSON2ADDR_1_1 - по полям addr,person
остальные - по одиночным полям
in с одним значением - поскольку запрос генерится автоматом и утт может быть несколько значений.
десяток миллионов записей в каждой таблице, инедксы по всем полям. На магических значениях - висим полчаса, 100% загрузка.
select person.link,person.fname,person.pname,person.sname,person.birthday from person_1 person,address_1 address,person2addr_1 p2a where person.fname=450 and person.pname=344 and person.sname=71921 and person.birthday between 18800101 and 19671231 and p2a.person=person.link and p2a.addr=address.link and address.street in (39346)
план
PLAN JOIN (ADDRESS INDEX (ADDRESS_STREET_1),PERSON INDEX (PERSON1_1,PERSON_BIRTHDAY_1),P2A INDEX (PERSON2ADDR_1_1))
индексы:
person1_1 - по полям fname,sname,pname
PERSON2ADDR_1_1 - по полям addr,person
остальные - по одиночным полям
in с одним значением - поскольку запрос генерится автоматом и утт может быть несколько значений.
десяток миллионов записей в каждой таблице, инедксы по всем полям. На магических значениях - висим полчаса, 100% загрузка.
1. Джойн через where - дурной тон.
2. Когда строишь запрос, сразу форматируй его. Это облегчит его понимание и тебе, и другим.
2. Попробуй вот так задать запрос:
select
person.link,
person.fname,
person.pname,
person.sname,
person.birthday
from
person_1 person
left join person2addr_1 p2a on person.link = p2a.person
left join address_1 address on p2a.addr = address.link
where
(person.fname=450)
and (person.pname=344)
and (person.sname=71921)
and (person.birthday between 18800101 and 19671231)
and (address.street in (39346))
Все условия взяты в скобки. Серверу в некоторых ситуациях все равно, а человеку понятнее. Особенно настораживает использование between без скобок.
4. Напиши, какой стал план.
2. Когда строишь запрос, сразу форматируй его. Это облегчит его понимание и тебе, и другим.
2. Попробуй вот так задать запрос:
select
person.link,
person.fname,
person.pname,
person.sname,
person.birthday
from
person_1 person
left join person2addr_1 p2a on person.link = p2a.person
left join address_1 address on p2a.addr = address.link
where
(person.fname=450)
and (person.pname=344)
and (person.sname=71921)
and (person.birthday between 18800101 and 19671231)
and (address.street in (39346))
Все условия взяты в скобки. Серверу в некоторых ситуациях все равно, а человеку понятнее. Особенно настораживает использование between без скобок.
4. Напиши, какой стал план.
Я не могу сразу форматировать запрос из-за того, что запросы у меня строятс яавтоматом и могут быть разными, в зависимости от входных значений. Этот еще очень хороший получился. Но зависает.
Попробую чуть позже и статистику возьму
Но что важно - виснет на строго определенной подборке входных значений. Перестройка статистики всех индексов, кстати, помогает - ранее виснувшие запросы начинабт работать. Но проявляются новые "висуны". Я на трогаю статистику пока специально, чтобы иметь нормальную воспроизводимость поблемы.
Попробую чуть позже и статистику возьму
Но что важно - виснет на строго определенной подборке входных значений. Перестройка статистики всех индексов, кстати, помогает - ранее виснувшие запросы начинабт работать. Но проявляются новые "висуны". Я на трогаю статистику пока специально, чтобы иметь нормальную воспроизводимость поблемы.
У меня тоже нет ни одного жестко написанного запроса. Всю работу по формированию вида запросов делают соответствующие методы. Что мешает тебе вместо, например, 'select ' + 'person.link' написать 'select'#13#10 + SpaceTab + 'person.link'?pticelov писал(а):Я не могу сразу форматировать запрос из-за того, что запросы у меня строятс яавтоматом и могут быть разными, в зависимости от входных значений.