Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» InterBase и FireBird: вопросы по работе и их решение

Автор: ant0ni02004
Дата сообщения: 30.11.2013 16:38
delover
set null - например для значения по умолчанию (таблица вида DefValue1_id, DefValue2_id, итд). on delete cascade - смысла нет (в ней есть и другие значения), restrict то же не подходит, а set null - самое то: удалили запись - и нет больше значения по умолчанию(null)
Автор: delover
Дата сообщения: 01.12.2013 11:40
volser

Цитата:
А можно пример где это используется

Да с удовольствием. У меня второстепенный справочник (двухслойный). Справочник - группы дисконтных карт. Специалисты раздают дисконтные карты и если покупатели с этими картами берут определённые товары то им отчисляется определённый процент. То есть на человека записывается список дисконтных карт и список товаров. Товары и дисконтные карты могут быть удалены из главных справочников, что при этом будет с группами дисконтных карт - не важно. Важно дать возможность удалить товары и карты. Товары удаляются например, когда из центрального офиса хотят чтобы данный товар стал синонимом другого товара. Дисконтные карты так же удаляются из центрального офиса - при удалении, любая связанная информация должна быть удалена, - она больше никого не интересует. Однако записи в группах желательно оставить и оставить накопления за период. Была дисконтная карта 3453534543 по ней было накопление вознаграждения 5р 30коп.

Добавлено:
volser
Да самое главное. Есть кнопка делающая расчёт всех продаж с выручкой и результаты записываются в темповую таблицу расчётов. Там все ключи set_null так как это всего лишь запись результатов длительного расчёта, чтобы не расчитывать заного пока работаем с определённым периодом. Важно чтобы суммы оставались не тронуты.
Автор: delover
Дата сообщения: 02.12.2013 11:07
Сегодня встретил такой справочник - Параметры ценообразования. В таблице товар есть ID_CALCPARAM setnull у него кей. Параметры можно использовать при ценообразовании, однако это вторичный справочник. Когда я удаляю параметр мне нужно чтобы он отапдейтил все товары на - нет связки.
Автор: jonikDk
Дата сообщения: 04.12.2013 12:05
delover
ну вот - если бизнес логика требует - используй и не парься
Автор: delover
Дата сообщения: 24.12.2013 16:16
А Вот такой вопрос (может даже обсуждение).
Есть выборка
select from T1 join T1.PK2=PrimariKey2 join PrimariKey3 join PrimariKeyN
Я меняю "join" на "left join" - и результат выборки в любом случае будет тот же...
План запроса в любом случае будет тот же.....

Кто знает почему left join выполняется быстрее? Я экономлю десятки и сотни миллисекунд. Оговорюсь. Все таблицы имеют нулевой ID для записей типа имя равно "_" и жёсткие форенкеи. То есть мне действительно без разницы LEFT или не LEFT. Тесты показывают что результаты сравнений нескольких миллионов NULL с NULL не занимают даже одну миллисекунду. В чём фишка - не пойму?
Автор: ant0ni02004
Дата сообщения: 24.12.2013 20:39
delover
а вы посмотрите на план выполнения запроса - сразу станет видно

потому что join - это всё равно что написать Select ... from t1,t2,... where...
и он перебирает всё подряд из всех возможных комбинаций t1*t2*....
а вот left join перебирает "поумнее"
Автор: delover
Дата сообщения: 25.12.2013 11:09
ant0ni02004
Спасибо за мнение. У меня план запроса не меняется. Я не знаю тех условий когда он меняется, план запроса до буквы - тот же. Разницы в left join и join нет никакой, только в одном случае результат сравнения я пихаю в добавление записи выборки, в другом случае не пихаю. То есть join обязан быть быстрее.
Автор: delover
Дата сообщения: 25.12.2013 15:46
Существует более правдоподобная версия. Дело в том, что пока я пишу LEFT, в это время сервер уже готовит записи. Ещё есть версии?
Автор: ant0ni02004
Дата сообщения: 25.12.2013 23:34
delover
не видя конкретных таблиц, данных, запросов и их планов (а тем более угадывать что там с ними делается в одном или другом случае) рассуждать тяжело. по теории запрос с join (where) и должен обрабатываться дольше чем с left join, но ведь и оптимизаторы запросов сейчас не те, что раньше были, могут неплохо ускорять
Автор: delover
Дата сообщения: 26.12.2013 05:24
ant0ni02004

Цитата:
не видя конкретных таблиц

Тут нет конкретики и не надо.

Дело в том, что когда имеем простой JOIN, есть вероятность, что в результирующей выборке будет ноль записей, следовательно результат строится динамически. Предположим у нас в результате возвращается 10 тысяч записей. Это значит, что под результат я буду 10 тысяч раз перераспределять память. Перераспределение это выделение памяти на одну запись больше, копирование памяти из старого куска, освобождение памяти старого куска. В случае с LEFT JOIN не существует смысла так поступать. Я заранее подготовлю кусок побольше и буду его заполнять без лишних телодвижений. То есть вместо 10 тысяч раз я обращусь к менеджеру памяти один раз. Конечно есть вероятность что сервер не пользуется земными технологиями, но я в это не верю. В любом случае я отдаю какие-то байты и эти байты где-то в памяти лежат. Если Вы независимо протестируете то увидите именно те миллисекунды, которые мы имеем в разнице между LEFT и простым JOIN.

Всем удачного Нового Года.
Автор: delover
Дата сообщения: 26.12.2013 08:55
ant0ni02004

Цитата:
запрос с join (where)

Ой, точно. Это хорошо, что Вы упомянули WHERE. Казалось бы наличие условия должно нам сказать что конечное количество записей не известно. Оказалось не так. Я нашёл свой конкретный запрос и там был WHERE. Видимо действительно инопланетные технологи. Дело в том, что если Вы возьмёте ассемблер, вернётесь в начало девяностых годов, поработаете с таблицей в которой указаны ассемблерные тики (количество тиков процессора), то Вам просто будет очевидно, что иногда лучше предварительно посчитать байты, а потом выделить блок памяти. Я точно подозреваю, что FireBird именно так и делает. Вероятно наличие индексов тоже влияет. Но не суть, суть в том что WHERE ещё ничего нам не говорит.
Автор: ant0ni02004
Дата сообщения: 26.12.2013 13:54
delover
под where я имел в виду вот что -
select ... from t1 join t2 on (условие) равносильно select ... from t1,t2 where (условие)
т.е. строятся все возможные комбинации из т1*т2 и проверяются на (условие)
а в случае select ... from t1 left join t2 on (условие) - идёт "склейка" по условию, что проще
а что касается использования индексов - так это уже внутреннее дело БД, особенно оптимизатора. и тут имеет значение в каком порядке, есть ли индексы, есть ли full scan итд. и оптимизатору firebird до оптимизатора oracle, например - расти и расти еще...
Автор: delover
Дата сообщения: 26.12.2013 16:06
ant0ni02004
Вы как в воду глядели. Я поторопился со where, where быть не должно по условию задачи. Когда я первый раз задал вопрос, мне начали отвечать что идут сравнения с null и об этом пишут все в интернете. Думаю задачка прикольная сама по себе. Будете прикалываться над коллегами - не забудьте про ассемблерные тики. Но время набегающих миллисекунд - именно то, что является издержками перераспределений.


Цитата:
и тут имеет значение в каком порядке, есть ли индексы

Нет индексов. По условию задачи джойны идут однотипно через форейн к примари.


Цитата:
все возможные комбинации из т1*т2

Ещё раз. В моём примере у join и left join абсолютно одинаковая математическая нагрузка - результирующая выборка одна и та же. Количество комбинаций одно и то же. Просто любое дополнительное условие отменит Count, что заставляет строить результат динамически. Отсутствие left это и есть дополнительное условие.
Автор: ant0ni02004
Дата сообщения: 26.12.2013 18:28
delover

Цитата:
Нет индексов. По условию задачи джойны идут однотипно через форейн к примари.

ну как же нет индексов? по праймари и по форейну индексы и берутся.

Цитата:
Количество комбинаций одно и то же

это результат один и тот же, а вот количество комбинаций, которые просматриваются для получения результата - разные (хотя опять же, умный оптимайзер может догадаться)

кроме того, может играть роль prepared у запросов (если у них действительно один и тот же план получается) - попробуйте их наоборот запускать - вдруг теперь и время поменяется соответственно, т.е. первый тормозит (т.к. его нужно еще prepare) а второй уже на всём готовеньком
Автор: delover
Дата сообщения: 27.12.2013 05:31

Цитата:
ну как же нет индексов? по праймари и по форейну индексы и берутся.

Вы имеете ввиду, что если я переименую PK_ то оптимизатор это не заметит? Я бы завязал на PK, зато картинка в плане красивая. Но это надо тестить ещё.


Цитата:
кроме того, может играть роль prepared у запросов

На эту шляпу я тестил, миллисекунды не то что предсказуемые, они для меня огромные. Все прозаичнее, есть и дисковая память и "Capacity" и даже препаред. Подозреваю, что даже есть разница в простом запросе и запросе который мы засунули в сохранёнку. Но эту разницу Вы увидите даже при отсутствии индексов кеев и прошитом пустом плане запроса.


Цитата:
это результат один и тот же, а вот количество комбинаций, которые просматриваются для получения результата - разные

Я так и думал что Вы немного не понимаете. Вы пишете t1*t2 при join. Это значит не арифметическое умножение а логическое (из математики множеств). Если Вы хотите пропихнуть арифметику Вы обязаны писать t1*index(t2) иначе индексы не имели бы такой популярности. В общем кто первый скажет слово Индекс - тот проиграл.
Автор: ant0ni02004
Дата сообщения: 27.12.2013 15:28
delover

Цитата:
Я так и думал что Вы немного не понимаете

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

Цитата:
пишете t1*t2 при join. Это значит не арифметическое умножение а логическое

вот его, Декартово произведение и имею в виду. какое же тут другое может быть
Автор: delover
Дата сообщения: 31.12.2013 12:44
ant0ni02004

Цитата:
вот его, Декартово произведение и имею в виду. какое же тут другое может быть

У Вас каша с комбинациями и индексами. Напомню (можете провикипежить), индексы были придуманы человечеством, чтобы не искать методом перебора всех комбинаций. При поиске по индексу уменьшается количество сравнений...

Например наша таблица это "куча", нет кластерного индекса. То есть данные не отсортированы, а вот ссылки в индексе отсортированы по значению поля. В классическом случае мы делим индекс (список ссылок) пополам. Берём среднюю ссылку и сравниваем значение поля с искомым. Если меньше, берём меньшую часть и снова делим пополам. Так мы делаем пока не найдём. То есть поиск в таблице с миллионом записей может быть равен трём значениям, хотя такой же поиск в таблице с тысячей записей будет равен десяти операциям сравнений.

Именно по этому количество операций сравнений равно функция от индекс.
Count(Join)=t1*index(t2),
Count(LeftJoin)=t1*index(t2)


Цитата:
это результат один и тот же, а вот количество комбинаций, которые просматриваются для получения результата - разные (хотя опять же, умный оптимайзер может догадаться)

Во первых и результат один и тот же и исходные данные одни и те же. Начертите в Экселе две таблицы с пятью записями и найдите случай когда Вам понадобится разное количество сравнений. Если получится, то считайте, что Нобелевскую премию Вы заработали. С обоими join абсолютно необходимо одинаковое математическое усилие.


Цитата:
оптимайзер может догадаться

Оптимайзер может "догататься", что если простой фильтрующий join по маленькой табличке выполнить раньше следующих join, то меньше нужно сравнений. Относительно left join это не касается.


Добавлено:
Я не рассматриваю случаи с не классическими индексами и смешенной организацией памяти базы - диск + ОЗУ. Так же исключена статистика индексов и так далее. Всё это может повлиять на выбор следующего join для оптимайзера, в моём примере PLAN одинаковый.
Автор: ant0ni02004
Дата сообщения: 31.12.2013 14:55
delover
Чисто теоретически - результаты при join не обязаны совпадать с результатами при leftjoin (т.к. при t1 left join t2 допускается отсутствие записей в t2 по условию leftjoin-а). То, что у Вас они одинаковые - так это by design, но ведь база догадаться об этом никак не может, ей никто не гарантирует, что для каждой записи в t1 всегда будут находиться соотв. записи в t2. Уже хотя бы поэтому будут разные алгоритмы обработки запросов. Как-то так.

С наступающим Новым Годом
Автор: delover
Дата сообщения: 07.01.2014 01:13
ant0ni02004
Ваше решение достаточно убедительно и является единственным. Версию про всякие количества рано исследовать. Вас с наступившим по старому. )
Автор: delover
Дата сообщения: 09.01.2014 09:14
С чем может быть связано, что по Local Engine база не зацепляется, хотя по Remote TCP\IP коннект удачный. Это связано не просто с Localhost, а именно с галочками Local\Remote. Мы переустановили сервер (Win7 32), даже с перезагрузками не помогло. Путь к библиотеке gds32 вообще никто не трогал. Правда одно недоразумение - база лежит в пути 'C:\'. Однако при тех же настройках IBExpert цепляется, штатный IBX цепляется, а вот FIB требует галочку Remote.
Автор: delover
Дата сообщения: 09.01.2014 12:15
Мы сделали следующее.
1) Установили 2.5.0.26074 Сервер (как мама велела).
2) Прописали путь к fbclient.dll (как бабушка велела).

После этого к базе на Рабочем Столе мы подсоединились, но вот на диске 'C:\' не получается. Хотя файл один и тот же, но пляски с бубнами остались. В общем процесс я запустил, но если кто знает ещё рецепты, прошу пишите.
Автор: egerLESHIK
Дата сообщения: 09.01.2014 14:20
delover

а, ODBC Драйвер под firebird устанавливали?
На днях после переустановки Windows тоже столкнулся с тем, что к базе в один день есть подключение, в другой день нет. Причина оказалась банальной - соединение отклонял брандмауэр windows. Значит или отключаем его, или добавляем программы, работающие с базой в исключения.
Автор: delover
Дата сообщения: 09.01.2014 16:22
egerLESHIK
Спасибо, кстати скорее всего так и есть. Просто ODBC я ещё слышал, а вот что такое брандмауэр "я не знаю". У нас только папочка FireBird и море компьютеров куда его ставят. А интересно чем диск C отличается от рабочего стола? Ну да ладно, Windows сейчас без ODBC поставляют, замучил я Вас.

Да, забыл упомянуть самое смешное. Мы в дизайне прописали папочку на рабочем столе, а при запуске программы читалась база с Ц диска. Так вот, мы пол часа гадали почему реально коннект есть, а у нас, при запуске программы полный абзац. Когда поняли что базы разные, вопрос решился. Но я понимаю, например autorun.inf, но с папками я так и не понял.
Автор: ant0ni02004
Дата сообщения: 09.01.2014 20:39
delover

Цитата:
А интересно чем диск C отличается от рабочего стола?

возможно, правами доступа отличается
Автор: delover
Дата сообщения: 10.01.2014 06:43
ant0ni02004

Цитата:
возможно, правами доступа отличается


Совершенно точно. Мы поставили пользователям те же галочки что и администраторам, и FireBird стал пускать к базе. Только учтите, что если поставите галочки, Windows будет шерстить все подпапки какие найдёт на диске. Естественно, сильно Вы не навредите, но так лучше не делать.
Автор: ant0ni02004
Дата сообщения: 10.01.2014 13:31
delover
а не проще ли было бы базу разместить в c:\database\ и права выдать на папку, чем на весь диск
Автор: delover
Дата сообщения: 10.01.2014 16:26
ant0ni02004
Так веть люди разные, бывают те кто например привык на диске в корне хранить. Например пожилые, те кто ещё к DOS привык. Ну и под старость бывает сложно вспомнить где, что почему и как. Если так надо, кому то, то просто любопытно.

А можно я прощения попрошу? Ну очень хочется. Тоже интересно, а можно ли сделать так чтобы IBExpert, когда бэкап делаешь запоминал кодировку, ведь это каждый раз ручками приходится вводить, когда переходишь с полторашки.
Автор: delover
Дата сообщения: 11.01.2014 17:05
Мне кажется, что можно и без прав админа, подключиться к базе. Нам же не привиделось - ставим local не работает, а tcp работает. Думаете я знаю что такое файловая система? Видимо как с join, - потому как может быть null, потому и алгоритмы разные.
Автор: ant0ni02004
Дата сообщения: 12.01.2014 14:08
delover

Цитата:
ставим local не работает, а tcp работает

ну так если соединяться с БД через tcp - то идёт обращение к службе. а служба, как правило, запускается системой с правами системы (что обычно больше, чем админские)
Автор: xpin2013
Дата сообщения: 17.01.2014 06:37
ant0ni02004
Локальное соединение подразумевает, что Вы может быть хотите "встроенный сервер", то есть embeded. Это действительная практика сервера, работающего без установки FireBird. Очень хорошо, что Вы правильно определили суть ошибки. Хорошо бы все понимали это обстоятельство.

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465

Предыдущая тема: Сравнение двух строк


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.