Время выполнения запроса
Время выполнения запроса
Перенес базу в одном из проектов с Access на Firebird 2.1.1 и столькнулся с непонятными мне тормозами, там где не тормозил Access, и где и тормозить-то нечему.
простейший prepared запрос
select CallTo,UserID,Len,Unsuccess,DialLength,DiscReason,StartTime from outcalls where incall=? order by id
возвращающий от 0 до 10 записей, требует 250-300 ms на каждое выполнение.
Таблица такая:
CREATE TABLE outcalls(ID INTEGER, INCALL INTEGER, CallTo CHAR(20), UserID INTEGER, StartTime timestamp, Len INTEGER, Unsuccess SMALLINT, DialLength SMALLINT, DiscReason SMALLINT)
К ней есть индексы:
CREATE UNIQUE INDEX OUTCALLS_ID ON outcalls(ID)
CREATE DESCENDING INDEX OUTCALLS_ID_D ON outcalls(ID)
CREATE INDEX outincall ON outcalls(INCALL)
CREATE INDEX outtime ON outcalls(StartTime)
CREATE INDEX outuser ON outcalls(UserID)
если я убираю order by - тормоза уходят
если я запрещаю индекс OUTCALLS_ID - тормоза уходят
откуда тормоза - просто не понимаю
простейший prepared запрос
select CallTo,UserID,Len,Unsuccess,DialLength,DiscReason,StartTime from outcalls where incall=? order by id
возвращающий от 0 до 10 записей, требует 250-300 ms на каждое выполнение.
Таблица такая:
CREATE TABLE outcalls(ID INTEGER, INCALL INTEGER, CallTo CHAR(20), UserID INTEGER, StartTime timestamp, Len INTEGER, Unsuccess SMALLINT, DialLength SMALLINT, DiscReason SMALLINT)
К ней есть индексы:
CREATE UNIQUE INDEX OUTCALLS_ID ON outcalls(ID)
CREATE DESCENDING INDEX OUTCALLS_ID_D ON outcalls(ID)
CREATE INDEX outincall ON outcalls(INCALL)
CREATE INDEX outtime ON outcalls(StartTime)
CREATE INDEX outuser ON outcalls(UserID)
если я убираю order by - тормоза уходят
если я запрещаю индекс OUTCALLS_ID - тормоза уходят
откуда тормоза - просто не понимаю
Re: Время выполнения запроса
Статистику индексную обновлял ? План и статистику выполнения покажи.
order by id + 0 тебе поможет, но нужно разобраться почему оно само не смогло
order by id + 0 тебе поможет, но нужно разобраться почему оно само не смогло
Re: Время выполнения запроса
Статистику обновил первым делом
Preparing query: select CallTo,UserID,Len,Unsuccess,DialLength,DiscReason,StartTime from outcalls where incall=1690114 order by id
Prepare time: 00:00:00.
PLAN (OUTCALLS ORDER OUTCALLS_ID INDEX (OUTINCALL))
Executing...
Done.
2431 fetches, 0 marks, 0 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 11 index, 0 seq.
Delta memory: -76 bytes.
Execute time: 00:00:00.
Script execution finished.
Preparing query: select CallTo,UserID,Len,Unsuccess,DialLength,DiscReason,StartTime from outcalls where incall=1690114 order by id
Prepare time: 00:00:00.
PLAN (OUTCALLS ORDER OUTCALLS_ID INDEX (OUTINCALL))
Executing...
Done.
2431 fetches, 0 marks, 0 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 11 index, 0 seq.
Delta memory: -76 bytes.
Execute time: 00:00:00.
Script execution finished.
Re: Время выполнения запроса
OUTCALLS ORDER OUTCALLS_ID тут мешает.
Сделай ORDER BY ID + 0
Сделай ORDER BY ID + 0
Re: Время выполнения запроса
Гммм ...
Но теоретически у меня там может оказаться и 500 записей. Что тогда будет из-за order by?
Но теоретически у меня там может оказаться и 500 записей. Что тогда будет из-за order by?
Re: Время выполнения запроса
кстати, а почему unique а не primary key?
Re: Время выполнения запроса
Все печально ...
250 ms на запрос мы победили ... Я на секунду расслабился ... правда общее время формирования отчета, в котором он использовался, все-таки увеличилось на 1.5 раза по сравнению с вариантом с драйвером access, но все-таки это было благопристойно. Зато другие отчеты ускорились примерно так же ... Но тут руки дошли до еще одного отчета, где такой же нехороший запрос использовался для сбора статистики по 3500 звонков (вызывался 3500 раз).
Оптимизированная версия отчета (без этого нехорошего запроса) формировалась 750 ms. Приемлимый результат (access чуть быстрее - 600-625, но это не критично). Отключаю оптимизацию и нехороший запрос начинает использоваться ... aceess 1300 ms (3500 нехороших запросов), firebird - 31000 ms. Нехороший запрос выполняется ~ 7 ms (иногда - дважды) и увеличивает врея выполнения в 20 раз.
Ни черта не понимаю. Запрос-то реально простой.
250 ms на запрос мы победили ... Я на секунду расслабился ... правда общее время формирования отчета, в котором он использовался, все-таки увеличилось на 1.5 раза по сравнению с вариантом с драйвером access, но все-таки это было благопристойно. Зато другие отчеты ускорились примерно так же ... Но тут руки дошли до еще одного отчета, где такой же нехороший запрос использовался для сбора статистики по 3500 звонков (вызывался 3500 раз).
Оптимизированная версия отчета (без этого нехорошего запроса) формировалась 750 ms. Приемлимый результат (access чуть быстрее - 600-625, но это не критично). Отключаю оптимизацию и нехороший запрос начинает использоваться ... aceess 1300 ms (3500 нехороших запросов), firebird - 31000 ms. Нехороший запрос выполняется ~ 7 ms (иногда - дважды) и увеличивает врея выполнения в 20 раз.
Ни черта не понимаю. Запрос-то реально простой.
Re: Время выполнения запроса
Да так исторически сложилось. Я не слишком продвинут в SQL и стараюсь использовать лишь простые вещи. А это влияет на производительность?kdv писал(а):кстати, а почему unique а не primary key?
Кстати, в access - primary key, кажется, был.
Re: Время выполнения запроса
на производительность не влияет, но primary key это первичный ключ, а unique - всего-лишь альтернативный ключ, т.е. вторичный по отношению к primary key.Да так исторически сложилось. Я не слишком продвинут в SQL и стараюсь использовать лишь простые вещи. А это влияет на производительность?
Re: Время выполнения запроса
Я понимаю, но контроль целостности силами сервера я не использую ни для чего, так что просто не знаю, к чему мне primary keykdv писал(а): на производительность не влияет, но primary key это первичный ключ, а unique - всего-лишь альтернативный ключ, т.е. вторичный по отношению к primary key.
Re: Время выполнения запроса
Сортировка, начиная с 2.0 выполняется в памяти, потому весьма быстра, и 10, или 500, или 2000 - особой погоды не сделает.pticelov писал(а):Но теоретически у меня там может оказаться и 500 записей. Что тогда будет из-за order by?
Оптимизирую процедуру за небольшое вознаграждение.pticelov писал(а):Все печально ...
Ни черта не понимаю. Запрос-то реально простой.
Если же есть конкретные вопросы, а не "почему тормозит то, на что я смотрю, и маааленький кусочек показал вам (да и то не совсем как у меня)", то можно и бесплатно помочь.
Re: Время выполнения запроса
А что вы собираетесь оптимизировать? Процедуру на абсолютно незнакомом Вам языке программирования, делающую быстро кучу своих дел, и имеющую единственное узкое место - этот запрос, который выполняется через ODBC? Весь прочий код там выполняется за разумное время, тормозит лишь этот запрос, хотя тормозить там просто нечему - запрос-то простой.WildSery писал(а): Оптимизирую процедуру за небольшое вознаграждение.
Если же есть конкретные вопросы, а не "почему тормозит то, на что я смотрю, и маааленький кусочек показал вам (да и то не совсем как у меня)", то можно и бесплатно помочь.
Я, конечно, могу всегда преписать принципиально код, который вызвыает этот запрос, сделав вместо 3500 запросов один, который всосет с запасом все потенциально подходящие записи в память и дальше я буду с массивом работать, но это - из разряда секса стоя в гамаке и для таких решений надо сначала понимать, почему это так себя ведет и поставить крест на нормальной работе с firebird.
На самом деле у меня сейчас есть вариант, не использующий это запрос, но мне-то надо понять, что происходит с ним, чтобы дальше нормально пользоваться firebird'ом
Re: Время выполнения запроса
то запрос, теперь выясняется, что это оказывается запрос в процедуре. Потом еще выяснится, что запрос выполняется через Execute statement?
убил напрочь. зачем тогда unique ? Вообще феерическая дискуссия. "У меня тут и запрос и процедура и ОДБЦ, и незнакомый язык процедур, и работает медленно (300 миллисекунд). Я хочу чтобы было быстрее, но оптимизировать мне это не надо."Я понимаю, но контроль целостности силами сервера я не использую ни для чего, так что просто не знаю, к чему мне primary key
Re: Время выполнения запроса
Гммм ... Вы подумали о процедурах в SQL? Нет, слово "процедура" не от туда. Замените на "кусок кода на незнакомом Вам языке программирования"kdv писал(а):то запрос, теперь выясняется, что это оказывается запрос в процедуре. Потом еще выяснится, что запрос выполняется через Execute statement?
Запрос выполняется через SQLExecute(), я же сказал - ODBC и prepared запрос.
А winsql подставил, когда DDL сгенерил для имеющейся базы. Когда 3 года назад этот проект делал, это была моя первая попытка работать с SQL. Поставил primary key. Потом, когда сгенерил DDL в winsql для переноса в firebird, он все первичные ключи превратил в unique, ну я и оставил как есть. Вреда в нем нет. Впрочем пользы - тоже.kdv писал(а):убил напрочь. зачем тогда unique ?Я понимаю, но контроль целостности силами сервера я не использую ни для чего, так что просто не знаю, к чему мне primary key
Это Вам так хочется это прочитать.Вообще феерическая дискуссия. "У меня тут и запрос и процедура и ОДБЦ, и незнакомый язык процедур, и работает медленно (300 миллисекунд). Я хочу чтобы было быстрее, но оптимизировать мне это не надо."
У меня тут программа, кусок которой написан на незнакомом вопрошающему товарищу языке программирования (встроенный язык этой системы). Программа работает с SQL через ODBC. Где-то там в формировании отчета используется prepared запрос. С первого захода он работал 250 ms, что было нереально много. Разобрались. Потом выяснилось, что даже с "order by id+0" он все равно работает не быстро - порядка 7 ms против долей миллесекунды при работе с той же БД через MS JET, что приводит к разрастанию времени выполнения моего кода до 30 s против 1.5 с jet'ом при обработке небольшого набора данных.
Оптимизация программы путем выкидывания этого запроса - это не решение данной проблемы. Я все-таки хочу понять, кто тормозит и убрать источник тормозов, а не хитро обойти тормоз, оставив себе проблему ну другой раз.
Re: Время выполнения запроса
под MS Jet имеется в виду Access? Если да, то я Вас огорчу - практически любой файловый движок в однопользовательском режиме работает быстрее, чем любой сервер SQL, тоже в однопользовательском режиме.работает не быстро - порядка 7 ms против долей миллесекунды при работе с той же БД через MS JET
Re: Время выполнения запроса
Я сначала писал Access, но потом решил писать правильно, чтобы не путать народ - jet через odbc из приложения, написанного на Си.kdv писал(а):под MS Jet имеется в виду Access? Если да, то я Вас огорчу - практически любой файловый движок в однопользовательском режиме работает быстрее, чем любой сервер SQL, тоже в однопользовательском режиме.работает не быстро - порядка 7 ms против долей миллесекунды при работе с той же БД через MS JET
режим многопользовательский, или я не понимаю о чем речь На всякий случай: с БД отдновременно могут работать разные приложения
Re: Время выполнения запроса
экакая витиеватость. Си, дельфи - какая разница? Что под Jet - база MDB (Access) ?Я сначала писал Access, но потом решил писать правильно, чтобы не путать народ - jet через odbc из приложения, написанного на Си.
могут, это понятно. Вопрос в том, как проводится тест - запрос выполняется "доли миллисекунды" при работе 50ти пользователей?режим многопользовательский, или я не понимаю о чем речь На всякий случай: с БД отдновременно могут работать разные приложения
Я не могу понять, почему Вас удивляет разница в скорости между файл-сервером и клиент-сервером. Вы же пытаетесь сравнить несравнимое. Сравните Jet с Ораклом и MS SQL в той же ситуации, например.
Re: Время выполнения запроса
Это клиент-сервер, тут другие подходы и выполнение 3500 раз даже отпрепаренного запроса просто не может быть моментальным, ибо данные гоняются через сетевой слой туда-сюда 3500 раз.pticelov писал(а):У меня тут программа, кусок которой написан на незнакомом вопрошающему товарищу языке программирования (встроенный язык этой системы). Программа работает с SQL через ODBC. Где-то там в формировании отчета используется prepared запрос. С первого захода он работал 250 ms, что было нереально много. Разобрались. Потом выяснилось, что даже с "order by id+0" он все равно работает не быстро - порядка 7 ms против долей миллесекунды при работе с той же БД через MS JET, что приводит к разрастанию времени выполнения моего кода до 30 s против 1.5 с jet'ом при обработке небольшого набора данных.
Хочется сравнения "в лоб" - возьми embedded.
Хочется как правильно - или выноси обработку на сервер, или избавляйся от 3500 вызовов
Re: Время выполнения запроса
+1.hvlad писал(а):Хочется как правильно - или выноси обработку на сервер, или избавляйся от 3500 вызовов
Нигде в здавом уме применять 3500 вызовов одного запроса мне и в голову не придёт (кроме закачки данных в биллинге, например, но это не селективный).
Пишется процедура, которая делает те же операции, либо возвращается результат сразу всех 3500 вызовов, и обрабатывается по одному в цикле, если с ними что-то в клиенте нужно делать.
Если расскажешь в двух словах, что делается, возьмусь посоветовать что-нибудь путное.
Re: Время выполнения запроса
А embedded работает через odbc? Вроде бы нет. Но в любом случае, эти 7 ms - это не накладные расходы от клиент-сервер. Потому что заливка данных в БД, где так же отдельный prepared запрос выполнялся для добавления каждой строки, прекрасно добавляля больше 5000 строк в секунду, т.е. все накладные расоды вместе со временем выполнения запроса не превышали 0.5 ms.hvlad писал(а):Это клиент-сервер, тут другие подходы и выполнение 3500 раз даже отпрепаренного запроса просто не может быть моментальным, ибо данные гоняются через сетевой слой туда-сюда 3500 раз.
Хочется сравнения "в лоб" - возьми embedded.
Хочется как правильно - или выноси обработку на сервер, или избавляйся от 3500 вызовов
У меня был еще один проект, в котором на этапе конвертирования данных при заливку в БД выполнялись поиски по куче таблиц (словари для фамилии, имени, отчества, городов, улиц, проверка на наличие дублей записей по нескольким параметрам), и firebird справлялся с несколькими сотнями добавлений в секунду, так что на весь кошмар из примерно десятка запросов уходило меньше 10 ms. А тут - 7 ms на один запрос.
И ключевой вопрос не в том, как обойти тормоз, а в том, как его убрать. А ведь у меня данные в БД поступают в реальном времени, и кое что проверяется там же, 7 ms на запрос - это смертоубийство.