- Вперед! - ответил Остап. - Не нойте, старик. Вас ждут золотые челюсти, толстенькая вдовушка и целый бассейн кефира.(Примечание: "Перфоманс в бассейне" это игра слов, своего рода литературный приём с использованием в одном контексте разных значений одних и тех же слов английского языка - "performance" и "pool".)
(И.Ильф, Е.Петров "Золотой теленок")
Идя на поводу у пожеланий трудящихся, вернувшихся сюда за добавкой, и развивая тему предыдущего поста "Oracle C++ Call Interface: экспресс-курс молодого шамана", необходимо несколько слов сказать об эффективности (performance).
В многопотоковых программах, в которых каждый поток существует относительно короткий промежуток времени, открытие соединения с базой для каждого потока может оказаться неэффективным решением, снижающим быстродействие. Для более эффективного использования ресурсов применяется пул соединений (Connection Pool) - некий ограниченный набор соединений, доступный для множества потоков. Для этого используется специальный метод createConnectionPool(). Как это все выглядит в коде?
Модифицируем пример из предыдущего поста, опустив повторяющиеся и несущественные для рассмотрения фрагменты кода:
class ProfilePool {
private:
Environment *env;
Connection *conn;
ConnectionPool *connPool;
Statement *stmt;
public:
ProfilePool(const string user, const string passwd, const string db) {
env = Environment::createEnvironment(Environment::DEFAULT);
unsigned int maxConn = 5;
unsigned int minConn = 3;
unsigned int incrConn = 2;
try {
connPool = env->createConnectionPool(
user, // The owner of the connection pool
passwd, // The password to gain access to the connection pool
db, // The database name that specifies the database server
// to which the connection pool is related
minConn, maxConn, incrConn);
cout << ((connPool) ? "SUCCESS" : "FAILURE") << " - createConnectionPool" << endl;
conn = connPool->createConnection(user, passwd);
cout << ((conn) ? "SUCCESS" : "FAILURE") << " - createConnection" << endl;
}
catch (SQLException ex) {
cout << "Exception thrown for createConnectionPool" << endl;
cout << "Error number: " << ex.getErrorCode() << endl;
cout << ex.getMessage() << endl;
}
}
~ProfilePool() {
connPool->terminateConnection(conn);
env->terminateConnectionPool(connPool);
Environment::terminateEnvironment(env);
}
void displayElements(const int rows = 5) {
...
}
};
int main(void) {
...
}
me@myhost ~/instantclient_11_2/sdk/demo $ ./profpool
SUCCESS - createConnectionPool
SUCCESS - createConnection
PROFILEID NAME DESCRIPTION BEH
========== ================================== ================================== ===
4160229888 RBS SuperChannel Circiut Profile RBS SuperChannel Circiut Profile 0
4366380032 Marconi Logic w/o MV n/a 0
4514160128 1. ECI LOGIC n/a 0
6028239872 AUX SDH-Egate Circuit LOT AUX SDH-Egate Circuit LOT profile 0
6032679936 AUX SDH-Egate Circuit LOP AUX SDH-Egate Circuit LOP profile 0
Done.
me@myhost ~/instantclient_11_2/sdk/demo $
Отдельного упоминания заслуживают три параметра minConn, maxConn, incrConn метода createConnectionPool().
minConn - это минимальное количество открытых соединений в пуле, которое создается при вызове данного метода.
Дополнительные соединения открываются по мере надобности (когда все открытые соединения заняты) с шагом incrConn,
но при этом общее количество открытых соединений не должно превышать значения параметра maxConn. Вероятно, разность maxConn и minConn должна быть кратна incrConn. Oracle скуп на рекомендации по выбору этих значений и ограничивается только упоминанием о том, что maxConn и incrConn должны быть больше или равны 1 и Generally, minConn should be set to the number of concurrent statements the application is expected to run, хотя здесь присутствует возможность тюнинга путем динамического конфигурирования значений этих атрибутов и автоматического закрытия соединений по таймауту.
Кстати, внутри одного Environment можно создать несколько пулов соединений, что может оказаться полезным для приложений, нуждающихся в load balancing.
Здесь есть еще много интересного, чем хотелось бы поделиться, и возможно, что время для этого когда-нибудь удастся найти. А пока в качестве дижестива могу предложить почитать: Optimizing Performance of C++ Applications.