Страница 26 из 27
Избыточная передача данных Самый простой способ диагностирования этой проблемы — использование монитора SQL-запросов. Заметьте, что большинство мониторов SQL не показывают объем переданных данных — эту опцию, как правило, необходимо включить вручную. Если избыточная передача данных замедляет работу приложения, это можно легко выявить с помощью монитора SQL. Для нормальной работы приложения необходимо, чтобы размер результирующего набора данных был небольшим. Разбиение на страницы результирующего набора данных взамен передачи всех данных (fetch all) иногда действительно может помочь. Также предоставляйте вашим пользователям средства для быстрого и эффективного поиска необходимых данных вместо бесконечных строк с долгим перемещением для позиционирования на необходимой записи. В качестве примера, чтобы не показывать тысячи записей с именами работников компании, добавьте индексные закладки с алфавитными указателями — тогда результирующий набор данных будет уже меньше как минимум раз в 20-25. Если даже такой вариант составляет большие наборы данных для каждой закладки, предоставьте пользователю возможность поиска необходимой записи — это лучше, чем выбирать информацию из длинного списка. Если у вас есть много наборов данных, передача их клиентскому приложению также может сильно сказаться на производительности, даже если размер этих наборов данных мал. Причины появления таких узких мест могут быть разными, поэтому ограничимся наиболее распространенными и приведем краткое их описание.
Причина: Использование BDE. Решение: Так как BDE может использовать только одну транзакцию в контексте одного подключения (несмотря на то, что сам InterBase такого ограничения не имеет), и подтверждение транзакции закрывает все без исключения активные курсоры, механизм BDE выполняет полную передачу записей (FetchAll) по всем открытым наборам данных, когда транзакция подтверждается (commit). Практически это выражается в том, что вызов метода TDataSet.Post в приложении, использующем BDE, вызывает выполнение метода FetchAll каждого набора данных внутри приложения. Самым лучшим решением в таком случае будет отказ от использования BDE и переход на работу со специализированными компонентами для InterBase, поддерживающими работу с несколькими транзакциями внутри одного подключения к базе данных. Если нет возможности обойти проблему, сократите до минимального количество одновременно открытых наборов данных и вызывайте FetchAll по их открытию (таким образом FetchAll для каждого набора данных не будут выполняться одновременно, когда пользователь отредактировал некоторую запись).
Причина: Использование lookup-полей. Решение: Когда вы используете lookup-поля вместо оператора JOIN, тогда lookup-таблицы (или их значительные части) должны быть переданы клиенту вместе с "основным" набором данных, когда тот активируется. Проблема состоит в том, что процесс поиска в lookup-полях происходит без использования индексной информации, ведь поиск производится на стороне клиента. Следует всегда пользоваться JOIN в SQL-запросах и отказаться от использования lookup-полей. Если все-таки необходимо использовать lookup-поля, кэшируйте необходимую информацию из статических таблиц путем сохранения в TClientDataSet.
Причина: Длительно активные транзакции. Решение: Решение лежит прямо на поверхности — просто не надо иметь в программе транзакций с большим временем жизни. Но существуют случаи, когда такие транзакции действительно необходимы. Будем считать, что мы используем InterBase 7.0 или выше (FireBird 1.5), и поэтому потеря производительности нас не затрагивает. Случается иногда, что даже такой выход не помогает, хотя подобные случаи крайне редки. Например, такое может случиться при длительной обработке данных сложной структуры, но даже в этом случае многое зависит от косвенных нюансов проектирования базы данных и специфики работы приложения. Также разработчики сталкиваются, но не часто, с проблемами использования длительно активных транзакций при пакетной обработке данных (так называемые "внутрикодовые" транзакции, которые несколько отличаются от транзакций, обслуживающих отображение данных). Решение проблемы вполне стандартно и самодостаточно и заключается в использовании в коде блока try … finally. Ведь, как правило, проблемы с длительно активными транзакциями проявляются сугубо при отображении информации в пользовательском интерфейсе.
Конечно, управление транзакциями осуществляется радикально отличающимися путями в зависимости от того, какой набор компонент вы используете для доступа к данным базы InterBase. Наборы компонент IBX, dbExpress, IBO и BDE, например, работают с транзакциями по своим схемам. Каждый из наборов работает с транзакциями по-своему, поэтому самым лучшим советом здесь будет тщательное изучение механизма работы с транзакциями тех компонентов, которые вы используете. Нельзя не упомянуть технологию DataSnap, которая предоставляет нейтральную, независимую от компонент методику управления транзакциями, работающую очень и очень хорошо и использующую очень короткие по времени активности транзакции. При использовании DataSnap появляется возможность даже радикальной смены компонент доступа без капитальной перестройки приложения. |