Что НЕ надо делать при работе с Interbase, Firebird, Yaffil

Этот документ сформирован по предложениям в конференции fido7.su.dbms.interbase. Здесь дан список того, что не надо (или категорически нельзя) делать при работе с Interbase/Firebird/Yaffil.

 

  1. Не надо логиниться к одной базе с разными путями
    В этом случае очень вероятно повреждение базы вплоть до ее полного уничтожения. Т.е. не надо использовать link-и на файлы и каталоги БД в unix, и не надо ошибаться и под win писать путь коннекта как c:dir\data.gdb вместо правильного c:\dir\data.gdb.
    этот совет не относится к разным именам одного и того же сервера в строке коннекта.
  2. Не надо выбирать на клиента большие обьемы данных
    Человек все равно не в состоянии просмотреть 100 000 записей :-)
  3. Не надо получать новый номер путем SELECT MAX(ID)+1
    при многопользовательской работе это 100%-ный источник конфликтов. Используйте генераторы.
  4. Не надо устанавливать значения генераторов (например в 0) внутри процедур и тем более триггеров
    опять же, при многопользовательской работе будут конфликты.
  5. Не надо делать большие расчеты в одной транзакции
    При больших операциях в одной транзакции сильно увеличивается объем памяти, используемой IB, что приводит к конкретным тормозам при нехватке оной.
    Если нет необходимости делать большой расчет (с большими изменениями данных) именно в одной транзакции, то лучше его разбить на части и провести в разных транзакциях. Это приведет к меньшему использованию памяти и ускорению расчета.
  6. Не надо делать PageSize = 1024 или 2048
    Устанавливайте при создании (или restore) для баз данных размер страницы 4 или 8 килобайт. При этом нужно чтобы логический диск был отформатирован с размером кластера идентичным размеру страницы. В Firebird и Yaffil можно использовать размер страницы 16К.
  7. Не надо делать коммит после каждой записи, если это не требуется по смыслу
    Это излишне нагружает сервер.
  8. Не надо делать commit после вставки каждой записи, если вы их вставляете больше 10 за один раз
    Interbase плохо работает в этом режиме, т.е. вставка будет медленной. Лучше оформить вставки "в пакет" и обрамить их StartTransaction/Commit.
  9. Не надо увлекаться ссылочной целостностью больше чем это требуется
    Не рекомендуется делать FK от больших таблиц на короткие справочники, в которых никогда не выполняются update и delete. Рекомендуется замещать такие FK контролем на триггерах и явным запретом модификации справочника в его триггерах.
    Кроме того, излишнее увлечение каскадным удалением, в совокупности с удалением через триггеры, может сильно запутать логику или привести к непредсказуемым удалениям или ошибкам нарушения целостности.
  10. Не создавайте ненужные индексы
    Помните, каждый индекс ускоряя выборку данных, замедляет добавление/изменение/удаление записей.
  11. Не стройте индексы по полям, содержащим наименьшее количество разных значений (например только 0 и 1, пол мужской/женский и т.п.)
    Если Вам все же надо такой индекс, то добавьте к нему еще одно поле, которое сделает его уникальным (такое поле должно идти перед наименее уникальным столбцом в списке полей индекса).
    Такие индексы заставляют сервер при поиске или выборках перебирать большое количество записей. Особенно это сказывается при чистке мусора после больших удалений.
  12. Не стройте индексы по полям PK, FK, UNIQUE
    IB автоматически создает соответствующие индексы при создании этих constraints.
  13. Не рекомендуется увлекаться outer join
    есть мнение, что null при наличии вторичных ключей это плохо, а кроме того оптимизатор при явных join действует совершенно определенным образом. Короче, не уверен - не используй.
  14. Не рекомендуется использовать связку "таблица+ХП"
    , т.е. явный или неявный join таблицы с хранимой процедурой. В некоторых ситуациях наблюдалось неправильное выполнение запроса (Например, от пеpемены мест слагаемых, "сумма" иногда меняется.). Также ситуации сильно зависят от версий IB (4.x, 5.x, 6.x) - в одной из версий это может привести к падению сервера, в другой не выполнится, а в третьей - пройдет.
  15. Не рекомендуется употреблять подзапросы в списочном контексте, то есть in (...), =all(...), =some(...).
    оптимизатор раскладывает FIELD IN (X, Y) в FIELD = X or FIELD = Y, соответственно чем больше элементов в IN, тем больше проверок приходится делать, и тем медленнее все это выполняется. Подумайте, может быть удастся заменить IN явным или неявным JOIN.
  16. Не надо увлекаться компонентом TTable и аналогичными
    TTable может выбрать все записи из большой таблицы, а также вы будете плохо знать SQL. Используйте TQuery и подобные.
  17. Нельзя создавать триггеры с именами вроде CHECK_xxx
    Префикс CHECK_ используется для "системных" триггеров, которые автоматически создаются при создании полей таблиц, имеющих check constraint. Возможно что в последующих версиях создание триггеров с такими именами будет вообще запрещено.
  18. Не рекомендуется создавать свои объекты с префиксом RDB$
    особенно триггеры на системные таблицы. После backup/restore такие объекты могут пропасть, или вести себя очень странно (нельзя удалить, нельзя изменить и т.п.) в зависимости от версии Interbase/Firebird/Yaffil.
  19. Не рекомендуется создавать роль (role) с именем любого из существующих пользователей
    если вам удастся это сделать (если еще не даны гранты для этого пользователя), то вы заблокируете доступ этого пользователя к базе данных. К тому же, впоследствии поведение может быть изменено, и создавать роль с именем пользователя (или наоборот) может быть запрещено.
  20. Не надо использовать тип FLOAT
    этот тип данных имеет длину 4 байта и точность всего 7 цифр. Эквивалентом в Delphi является single. Если хотите использовать вещественные числа, то сначала попробуйте перемножить и поделить два таких числа прямо в Delphi - так вы увидите точность вычислений, что исключит впоследствии проблемы с хранением и обработкой таких данных в базе.
  21. Не используйте маски (*.gdb) для gbak!!!
    Использование для gbak масок на Unix или "парных" параметров на Windows вроде
    gbak -b /db/*.gdb /bk/*.gbk
    gbak -b a.gdb a.gbk b.gdb b.gbk
    может привести к удалению ВСЕХ баз данных в указанном каталоге и бэкапов после бэкапа первого обработанного файла.
  22. Не создавайте столбцы с одинаковыми именами но в разном регистре в третьем диалекте
    В третьем диалекте (IB6.0 и выше) есть возможность создать таблицу вида
    create table X ("Id" integer, "iD" integer); (см. faq по диалектам). При этом сервер будет работать с такими столбцами нормально, однако не все клиентские компоненты смогут нормально обрабатывать такие имена как минимум в FieldByName.
    Собственно, именование объектов в двойных кавычках необязательно для третьего диалекта.
  23. Не надо копировать базу обычной файловой командой (операцией) copy в то время, когда сервер работает с базой.
    Файл БД это файл произвольного доступа. А копирование (не gbak) осуществляется поблочно. Поэтому пока часть базы "скопируется", она уже может успеть измениться несколько раз. Как результат, копию БД можно будет сразу отправить в "корзину".
  24. Не надо делать restore (gbak -r) поверх существующей базы данных.
    Если вдруг restore не пройдет - вы окажетесь без рабочей базы данных, и без восстанавливаемого бэкапа.
  25. Ни в коем случае не меняйте во время работы доменное имя сервера.
    IB/FB/YA используют имя сервера для именования lock-файла, поэтому в Classic это может привести к порче базы данных (два lck-файла с разными именами для разных процессов Classic).
  26. Нельзя в одной транзакции менять медаданные и тут же выполнять запросы, которые используют эти метаданные
    Изменение метаданных зачастую это операция, которая реально применяется только по commit. При этом для текущей транзакции видны изменения этих самых метаданных. Поэтому ни в коем случае нельзя делать нечто вроде
    alter table add field1 int
    update table set field1 = 10
    ISQL и ряд других инструментов при выполнении операторов DDL опознают это и действуют в режиме autocommit. В IB API ограничения на выполнение DDL и DML нет, т.е. разработчик сам должен знать о таком поведении сервера.
  27. Не нужно смешивать в одном запросе синтаксис явных и неявных JOIN
    При этом сервер или не выполнит запрос (ошибка), или вернет результат, который вы вовсе не ожидаете. В запросе целиком нужно использовать или только явные JOIN, или только неявные.