Что НЕ надо делать в InterBase и Firebird?

Этот документ сформирован по предложениям в конференции fido7.su.dbms.interbase. Здесь дан список того, что не надо (или категорически нельзя) делать при работе с InterBase/Firebird/Yaffil.
Последние обновления, указана дата и номера новых или изменившихся пунктов – 19.03.2001, 05.10.2001 (+17), 08.07.2002, (+18), 09.07.2002 дополнены определения некоторых пунктов и добавлен пункт 19, 10.07.2002 (+20), 19.03.2003 (+21), 21.06.2003 (+22), 15.08.2003 (+23,+24), 24.02.2004 (+25), 25.03.2004 (+26), 26.05.2004 (+27, u9), 14.12.2004(+28).
 
  1. Не надо логиниться к одной базе с разными путями
В этом случае очень вероятно повреждение базы вплоть до ее полного уничтожения. Т. е. не надо использовать link-и на файлы и каталоги БД в Unix, и не надо ошибаться и под win писать путь коннекта как c:dir\data.gdb вместо правильного c:\dir\data.gdb.
Этот совет не относится к разным именам одного и того же сервера в строке коннекта.
 
  1. Не надо выбирать на клиента большие обьемы данных
Человек все равно не в состоянии просмотреть 100 000 записей :-)
 
  1. Не надо получать новый номер путем SELECT MAX(ID)+1
При многопользовательской работе это 100%-ный источник конфликтов. Используйте генераторыLINK.
 
  1. Не надо устанавливать значения генераторов (например в 0) внутри процедур и тем более триггеров
Опять же, при многопользовательской работе будут конфликты.
 
  1. Не надо делать большие расчеты в одной транзакции
При больших операциях в одной транзакции сильно увеличивается объем памяти, используемой IB, что приводит к конкретным тормозам при нехватке оной.
Если нет необходимости делать большой расчет (с большими изменениями данных) именно в одной транзакции, то лучше его разбить на части и провести в разных транзакциях. Это приведет к меньшему использованию памяти и ускорению расчета. Также см. savepointsLINK.
 
  1. Не надо делать PageSize = 1024 или 2048
Устанавливайте при создании (или restore) для баз данных размер страницы 4 или 8 килобайт. При этом нужно чтобы логический диск был отформатирован с размером кластера идентичным размеру страницы. В Firebird и Yaffil можно использовать размер страницы 16К.
 
  1. Не надо делать коммит после каждой записи, если это не требуется по смыслу
Это излишне нагружает сервер.
 
  1. Не надо делать commit после вставки каждой записи, если вы их вставляете больше 10 за один раз
InterBase плохо работает в этом режиме, т. е. вставка будет медленной. Лучше оформить вставки "в пакет" и обрамить их StartTransaction/Commit.
 
  1. Не надо увлекаться ссылочной целостностью больше, чем это требуется
Не рекомендуется делать FK от больших таблиц на короткие справочники, в которых никогда не выполняются update и delete. Рекомендуется замещать такие FK контролем на триггерах и явным запретом модификации справочника в его триггерах.
Кроме того, излишнее увлечение каскадным удалением, в совокупности с удалением через триггеры, может сильно запутать логику или привести к непредсказуемым удалениям или ошибкам нарушения целостности.
 
  1. Не создавайте ненужные индексы
Помните, каждый индекс ускоряя выборку данных, замедляет добавление/изменение/удаление записей.
 
  1. Не стройте индексы по полям, содержащим наименьшее количество разных значений (например, только 0 и 1, пол мужской/женский и т. п.)
Если Вам все же надо такой индекс, то добавьте к нему еще одно поле, которое сделает индекс более "уникальным".
Индексы с большим числом дубликатов ключей сильно замедляют сборку мусораLINK (до IB 7.5 и Firebird 2.0).
 
  1. Не стройте индексы по полям PK, FK, UNIQUE
IB автоматически создает соответствующие индексы при создании этих constraints.
 
  1. Не рекомендуется увлекаться outer join
Есть мнение, что null при наличии вторичных ключей это плохо, а кроме того оптимизатор при явных join действует совершенно определенным образом. Короче, не уверен – не используй.
 
  1. Не рекомендуется использовать связку "таблица+ХП", т. е. явный или неявный join таблицы с хранимой процедурой
В некоторых ситуациях наблюдалось неправильное выполнение запроса (Например, от пеpемены мест слагаемых, "сумма" иногда меняется.). Также ситуации сильно зависят от версий IB (4.x, 5.x, 6.x) - в одной из версий это может привести к падению сервера, в другой не выполнится, а в третьей – пройдет.
 
  1. Не рекомендуется употреблять подзапросы в списочном контексте, то есть in (...), =all(...), =some(...)
Оптимизатор раскладывает FIELD IN (X, Y) в FIELD = X or FIELD = Y, соответственно чем больше элементов в IN, тем больше проверок приходится делать, и тем медленнее все это выполняется. Подумайте, может быть удастся заменить IN явным или неявным JOIN.
 
  1. Не надо увлекаться компонентом TTable и аналогичными
TTable может выбрать все записи из большой таблицы, а также вы будете плохо знать SQL. Используйте TQuery и подобные.
 
  1. Нельзя создавать триггеры с именами вроде CHECK_xxx
Префикс CHECK_ используется для "системных" триггеров, которые автоматически создаются при создании полей таблиц, имеющих check constraint. Возможно что в последующих версиях создание триггеров с такими именами будет вообще запрещено.
 
  1. Не рекомендуется создавать свои объекты с префиксом RDB$
Особенно триггеры на системные таблицы. После backup/restore такие объекты могут пропасть, или вести себя очень странно (нельзя удалить, нельзя изменить и т. п.) в зависимости от версии InterBase/Firebird/Yaffil.
 
  1. Не рекомендуется создавать роль (role) с именем любого из существующих пользователей
Если вам удастся это сделать (если еще не даны гранты для этого пользователя), то вы заблокируете доступ этого пользователя к базе данных. К тому же впоследствии поведение может быть изменено, и создавать роль с именем пользователя (или наоборот) может быть запрещено.
 
  1. Не надо использовать тип FLOAT
Этот тип данных имеет длину 4 байта и точность всего 7 цифр. Эквивалентом в Delphi является single. Если хотите использовать вещественные числа, то сначала попробуйте перемножить и поделить два таких числа прямо в Delphi  так вы увидите точность вычислений, что исключит впоследствии проблемы с хранением и обработкой таких данных в базе.
 
  1. Не используйте маски (*.gdb) для gbak!!!
Использование для gbak масок на Unix или "парных" параметров на Windows вроде
gbak -b /db/*.gdb /bk/*.gbk
gbak -b a.gdb a.gbk b.gdb b.gbk
может привести к удалению ВСЕХ баз данных в указанном каталоге и бэкапов после бэкапа первого обработанного файла.
 
  1. Не создавайте столбцы с одинаковыми именами но в разном регистре в третьем диалекте
В третьем диалекте (IB6.0 и выше) есть возможность создать таблицу вида
create table X ("Id" integer, "iD" integer); (см. FAQ по диалектам). При этом сервер будет работать с такими столбцами нормально, однако не все клиентские компоненты смогут нормально обрабатывать такие имена как минимум в FieldByName.
Собственно, именование объектов в двойных кавычках необязательно для третьего диалекта.
 
  1. Не надо копировать базу обычной файловой командой (операцией) copy в то время, когда сервер работает с базой
Файл БД это файл произвольного доступа. А копирование (не gbak) осуществляется поблочно. Поэтому пока часть базы "скопируется", она уже может успеть измениться несколько раз. Как результат, копию БД можно будет сразу отправить в "корзину".
 
  1. Не надо делать restore (gbak -r) поверх существующей базы данных
Если вдругLINK restore не пройдет  вы окажетесь без рабочей базы данных, и без восстанавливаемого бэкапа.
 
  1. Ни в коем случае не меняйте во время работы доменное имя сервера
IB/FB/YA используют имя сервера для именования lock-файла, поэтому в Classic это может привести к порче базы данных (два lck-файла с разными именами для разных процессов Classic).
 
  1. Нельзя в одной транзакции менять медаданные и тут же выполнять запросы, которые используют эти метаданные
Изменение метаданных зачастую это операция, которая реально применяется только по commit. При этом для текущей транзакции видны изменения этих самых метаданных. Поэтому ни в коем случае нельзя делать нечто вроде
alter table add field1 int
update table set field1 = 10
ISQL и ряд других инструментов при выполнении операторов DDL опознают это и действуют в режиме autocommit. В IB API ограничения на выполнение DDL и DML нет, т. е. разработчик сам должен знать о таком поведении сервера.
 
  1. Не нужно смешивать в одном запросе синтаксис явных и неявных JOIN
При этом сервер или не выполнит запрос (ошибка), или вернет результат, который вы вовсе не ожидаете. В запросе целиком нужно использовать или только явные JOIN, или только неявные.
 
  1. Не рекомендуется делать backup на логический диск с базой данных
Это чаще всего чревато порчей БД и бэкапа из-за отсутствия доступного на диске места. Лучше всего, с точки зрения скорости, бэкап делать на отдельный физический диск.
 
(c) коллективный разум fido7.su.dbms.interbase, news://forums.demo.ru/epsylon.public.interbase
впервые опубликовано на www.ibase.ru

Подпишитесь на новости Firebird в России

Подписаться