firebird+Python, мелкие вопросы по оптимизации.

sKotenok
Дата: 18.06.2012 02:37:28
Здравствуйте всем, приходится писать мелкие костыли скрипты под Firebird - обвязку над "Большой Программой", делающие что-нибудь полезное.
Накопилась кучка вопросов. Если разнести их по отдельным темам, потом сам запутаюсь, так что не ругайтесь, что все тут.
Скрипты уже работают (Python+kinterbasdb), во время писания не заморачивался никакой оптимизацией, оставляя на потом. Думаю это потом как раз наступило :)
Теперь к делу:
БД на firebird2.5, ClassicServer, Linux. Основная таблица ORDERS ~100k записей и растет, остальное - обвязка, история, логи и т.п.
Нужные ключи: ID и STATE, остальные - доп. инфа (150 полей!) тяну по мере надобности.
ID - уникальные, генераторные, PrimaryKey. STATE - штук 30 состояний из отдельной таблицы как ForeignKey
В плане общения с базой все скрипты можно представить так (N и NN - просто какие-то числа):
N раз: Select SOME from ORDERS where STATE=NN
N раз: Select SOME from ORDERS where ID=NN
----Не связанная с БД логика на 100500 строк----
N раз: Update ORDERS set SOME=... where ID=NN
N раз Delete from ORDERS where ID=NN
N раз Insert into ORDERS {} values ({})
fb.commit()
и так в цикле до 2го пришествия. Явно транзакциями не пользуюсь вообще. kinterbasdb это все делает сам.
1 Вопрос простой - как это все пишут нормальные разработчики? (скажем, стоит ли объединить селекты в 1 большой, мне не влом потом в цикле пробежаться, раскидать значения куда нужно). Читал где-то здесь, что Select SOME from .. where ID==NN or ID=NNN or ... (тут штук 50 ID, или штук 10-15 STATE-ов) напрягает базу сильнее, чем отдельные запросы.
И где бы почитать про работу с транзакциями именно в Firebird?
2 Вопрос. В kinterbasdb так и не нашел средства проверить коннект к базе, в смысле живо оно там, али что не так.
Как это вообще сделать можно?
3 Вопрос. Теперь чуть-чуть веселее. В одном из скриптов я добавляю заказ в БД, проблема в том, что ID должен создаваться генератором, а он мне нужен: после вставки я какое-то время слежу за заказом и меняю его как мне хочется.
Обходной путь я выбрал: вставляю заказы в БД, делаю commit в середине скрипта, потом вытаскиваю их по специально для этого выставленному STATE, потом опять меняю статусы пачкой Update, чтобы Большую Программу не путать. Происходит все быстро, и никто не замечает. Но самому такая бяка не нравится. Может как попроще можно сделать?
4 Вопрос. В догонку. Что лучше для FB, держать коннект постоянно, или периодически закрывать\открывать заново?
И есть ли вообще где-нибудь нормальная актуальная литература по Firebird? Проблема не в том, что ничего нету, скажем на http://www.ibase.ru/interbase.htm#doc я побывал. Сильно не хватает инфы, как этим зверем пользоваться, чего оно любит, что не очень, почему что-то стоит делать так, а что-то иначе. В общем нормального УЧЕБНИКА. Ну и зачем Firebird, а не, скажем, мускул или постгре.
Спасибо всем, кто откликнется.
Граур Станислав
Дата: 18.06.2012 06:17:13
sKotenok
3 Вопрос. Теперь чуть-чуть веселее. В одном из скриптов я добавляю заказ в БД, проблема в том, что ID должен создаваться генератором, а он мне нужен: после вставки я какое-то время слежу за заказом и меняю его как мне хочется. Может как попроще можно сделать?


Прочитать http://www.ibase.ru/devinfo/generator.htm


sKotenok
4 Вопрос.
И есть ли вообще где-нибудь нормальная актуальная литература по Firebird? Проблема не в том, что ничего нету, скажем на http://www.ibase.ru/interbase.htm#doc я побывал.


Побывать еще на http://www.ibase.ru/develop.htm
Там же ссылки на книги. Хелен Борри и Ковязин, Востриков
Dimitry Sibiryakov
Дата: 18.06.2012 11:10:04

sKotenok
Сильно не хватает инфы, как этим зверем пользоваться, чего оно любит, что не очень, почему
что-то стоит делать так, а что-то иначе.

Как-то ты неправильно на ibase.ru побывал. Видимо, остановился на первом разделе. Всё
запрошенное там есть. Начни с чтения FAQ.

Posted via ActualForum NNTP Server 1.5

sKotenok
Дата: 20.06.2012 17:06:50
Спасибо за оба ответа.
http://www.ibase.ru/devinfo/generator.htm - почитал внимательнее. Оказалось, Firebird поддерживает Insert ... Returning, это решило 3 вопрос полностью.
Также скачал пару книжек, пока что чукча писатель - читать некогда, позже посмотрю, думаю большинство вопросов сами по себе отпадут.
Чего наврятли будет в книгах - что создает меньшую нагрузку на сервер - один Select .. Where 1 or 2 or 3 or ... or 100, или 100 одиночных селектов в цикле? или есть способ получше для такого запроса?
Может быть Select .. Where ID in (1,2,....,100)?
Таблоид
Дата: 21.06.2012 02:15:44
sKotenok
или есть способ получше для такого запроса?
Да, есть. Выбранные ID'шники надо предварительно записывать в таблицу (т.е. "длинный" in-список транспонировать в "высокий" проиндексированный столбец).
Затем соединять основную таблицу с выбранной.
Потери произв-сти при 100 элементах я не заметил. Но сильно подозреваю, что на кол-ве ~1000 разница уже будет заметна (вариант с IN будет проигрывать, если для ID'шников находятся числа в конце списка, а не в начале).
Test:
+
set echo on;
recreate table t_main(id int primary key);
commit;

recreate table t_selected(id int primary key);
commit;
-------------------------------
insert into t_main(id)
with recursive
r as(select 0 i from rdb$database union all select i+1 from r where r.i<999)
select n1.i*1000+n0.i
from r n1,r n0
order by rand();
commit;

insert into t_selected(id)
with recursive
r as(select 0 i from rdb$database union all select i+1 from r where r.i<9)
select n1.i*10+n0.i
from r n1,r n0;
commit;

set stat on;
select count(*)
from t_main
where id in (
1, 11, 21, 31, 41, 51, 61, 71, 81, 91,
2, 12, 22, 32, 42, 52, 62, 72, 82, 92,
3, 13, 23, 33, 43, 53, 63, 73, 83, 93,
4, 14, 24, 34, 44, 54, 64, 74, 84, 94,
5, 15, 25, 35, 45, 55, 65, 75, 85, 95,
6, 16, 26, 36, 46, 56, 66, 76, 86, 96,
7, 17, 27, 37, 47, 57, 67, 77, 87, 97,
8, 18, 28, 38, 48, 58, 68, 78, 88, 98,
9, 19, 29, 39, 49, 59, 69, 79, 89, 99,
10, 20, 30, 40, 50, 60, 70, 80, 90, 100
);

select count(*)
from t_main m
join t_selected s on m.id=s.id;
set stat off;
commit;


/* результат на обычной рабочей станции:
COUNT
============
100

Current memory = 71909016
Delta memory = 187704
Max memory = 81663420
Elapsed time= 0.00 sec
Buffers = 16384
Reads = 0
Writes 0
Fetches = 616

select count(*)
from t_main m
join t_selected s on m.id=s.id;

COUNT
============
100

Current memory = 71731064
Delta memory = -177952
Max memory = 81663420
Elapsed time= 0.02 sec
Buffers = 16384
Reads = 0
Writes 0
Fetches = 825
set stat off;
commit;
*/
ЗЫ. Кроме того, где-то читал, что вроде было в ФБ (ИБ ?) ограничение на 1500 элементов для IN-списка.
sKotenok
Дата: 27.06.2012 13:21:09
To: Таблоид спасибо за совет, пока некогда было разбираться.
В целом думаю, вы правы - в пределах сотни извлекаемых записей разницы нет, но открыл для себя кое-что новое.

На днях директор зашла в гости к конкурентам.. и купила их.., поэтому работы у меня прибавилось.
Теперь интересное:
У наших конкурентов работает написанный на коленке аналог нашей Серьезной и Дорогой программы. И поднято оно на мускуле+php. Т.к. теперь они - наш филиал, рано или поздно придется либо ставить наше ПО им, либо допиливать их программку и внедрять у нас. За неделю поковырял немного, как все у них организовано, поэтому есть с чем сравнивать.

Пара мелких вопросов по организации хранения данных:

1) У нас все заказы живут в одной большой таблице на 150+ полей без какого-либо разделения. На мускуле таблица разбита на 3 части, что для MySQL нормально (я бы так же сделал) - часто используемые заказы в 2х таблицах - в 1й только поля постоянного размера, в другой - блобы, текст и т.п., которые подгружаются по запросу и соотв. требуются реже. в 3ю скидываются старые уже закрытые заказы.
Не думаю, что "наши" разработчики совсем лентяи, хотя ... - что у нас крутится на 4х-вёдерном ксеоне, там работает на типовом офисном ПК (селерон+Гиг ОЗУ) и явно пошустрее. При этом объем заказов у них меньше где-то в 2 раза.
Сам вопрос - это нормально для Firebird - хранить данные в одной большой таблице?

2 В нашей базе куча триггеров на каждый чих (500+ на 150) таблиц. При чем в часто используемых таблицах триггеры довольно большие на мой взгляд и делают кучу всего. Думаю, примерно треть прикладной логики у нас написана на триггерах.
Тот же вопрос - в Firebird так и пишут, т.е. он заточен под это? Мне мускул привычнее и на нем я триггеры стараюсь свести к необходимому минимуму, вынося логику на сервер.
Таблоид
Дата: 27.06.2012 13:54:06
sKotenok
1) <...> это нормально для Firebird - хранить данные в одной большой таблице?

2 <...> Тот же вопрос - в Firebird так и пишут, т.е. он заточен под это? Мне мускул привычнее и на нем я триггеры стараюсь свести к необходимому минимуму, вынося логику на сервер.
1. Это НЕнормально в любой реляционной СУБД. Для чего была придумана нормализация, как думаете ?
2. Код в триггерах выполняется ТАК ЖЕ НА СЕРВЕРЕ. Если вы говорите про вынос кода в хранимые процедуры, вызываемые из триггеров, то если код не очень объёмный, оставьте его внутри триггеров. Различия в скорости вып-я кода внутри триггеров vs внутри ХП - отсутствуют. А вот если вы говорите про замену, где возможно, триггеров на декларативные ограничения - то да, это обязательно надо делать. Ибо триггеры выполняются в контексте транзакций, а декл. ограничения (PK/unique, FK) действуют вне их.
Ivan_Pisarevsky
Дата: 27.06.2012 14:25:47
sKotenok
Сам вопрос - это нормально для Firebird - хранить данные в одной большой таблице?
Смотря как. :) Если с умом, то можно, и триггеры также.
Спор из разряда кто кого "боксер или каратист"?
miwaonline
Дата: 27.06.2012 17:10:10
sKotenok
...
Думаю, примерно треть прикладной логики у нас написана на триггерах.
Тот же вопрос - в Firebird так и пишут, т.е. он заточен под это? Мне мускул привычнее и на нем я триггеры стараюсь свести к необходимому минимуму, вынося логику на сервер.

Только я не понял выделенное предложение? Если да - тогда проясните кто-нить, пожалуйста.
Dimitry Sibiryakov
Дата: 27.06.2012 17:12:40

miwaonline
Если да - тогда проясните кто-нить, пожалуйста

Трехзвенка: сервер приложений. Мускуль используется как тупое хранилище - единственное с
чем он более-менее справляется.

Posted via ActualForum NNTP Server 1.5