なぜLinux版にするかといえば、「数百倍以上高速」だ
からです。
DBデータカルテストレージとしてPostgreSQLを使うならWindows版で充分です、
実際にそういう使い方がほとんどですのでコンピュータも遅い旧世代でよいかもしれません。
ところが数十万レコード以上の数値を複雑に演算しなければならないシステムですと、
多量の関連情報をLAN網を経てWindowsクライアントが操作していたら実現しません。
なにしろLAN網は超低速です。
複雑なSQL記述を駆使して高速な turbolinux11server PostgreSQLサーバに演算処理をさせるのも手法ですが、
難解でありプログラムの保守性可用性が著しく劣ります。(仕事になりません。)
「PostgreSQLには自サーバー内に動いている自作プログラムへ通知
する機能を持っています。」
この機能を使えば複雑な演算をPostgreSQLサーバで速攻に処理できます。
サーバも負荷に耐えうる良いスペックが必要です。
(おおよそですがselect128列10万行演算でRAM256MB食います。)
よろしければ参考にしてください。
注意:ソースリストはDB名を適切にすれば、末尾の「bd.c」(C言語ソースではない)でコンパイル、
turbolinux11server で動作しますが紹介用です。趣旨を理解せず、このまま拡張しないように。
ソースリスト
'notify.c----------------------------------------------------------------------------------------------------
/*
* notify.c : 非同期通知インターフェース
*
* Visual Basic 2008 などから発行するノンクエリSQL
* Dim SQL1 as String = "NOTIFY command1"
* Dim SQL2 as String = "NOTIFY command2"
* Dim SQL3 as String = "NOTIFY command3" '停止
*/
#include <stdio.h>
#include <string.h>
#include "postgres.h"
#include "libpq-fe.h"
/************************************************************************************/
void exit_nicely(PGconn *conn)
{
PQfinish(conn);
exit(1);
}
void mycommand1(int ii_pidCD);
void mycommand2(int ii_pidCD);
main()
{
/************************************************************************************/
char
ic_256[256]; /* 汎用文字列[要素数] */
/************************************************************************************/
char ic_LISTEN[]="LISTEN ";
char ic_pidCD[12];
char ic_Command1[] = "command1";
char ic_Command2[] = "command2";
char ic_Command3[] = "command3";
PGnotify *notify;
/************************************************************************************/
char
ic_SQL[4096];
/* SQL */
/************************************************************************************/
char *pghost; /*
接続するコンピュータバックエンド */
char *pgport; /*
接続するコンピュータのバックエンドポート */
char *pgoptions; /*
バックエンドのスタートアップオプション */
char *pgtty;
/* バックエンドのデバッグ用 tty */
char *dbName; /*
データベース名 */
PGconn
*conn; /* コネクション・ファイルハンドル */
PGresult *res;
/* 戻り値 */
/* NULL なら環境変数.そこに見つからない場合はデフォルト定数. */
pghost = NULL;
/* バックエンドが動作しているサーバのホスト名 */
pgport = NULL;
/* バックエンドのポート番号 */
pgoptions = NULL; /*
バックエンドのスタートアップオプション */
pgtty = NULL;
/* バックエンドのデバッグ用 tty */
dbName = "sampledb"; /* データベース名 */
conn =
PQsetdb(pghost,pgport,pgoptions,pgtty,dbName);
/* バックエンドとの接続が成功したことを確認 */
if (PQstatus(conn) == CONNECTION_BAD)
{
printf("Database '%s' Connection
Eror!\n",dbName);
fprintf(stderr,"%s",PQerrorMessage(conn));
exit_nicely(conn);
}
/************************************************************************************/
strcpy(ic_SQL,ic_LISTEN);
strcat(ic_SQL,ic_Command1);
res = PQexec(conn,ic_SQL);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr,"'%s'Into
Error!\n",ic_Command1);
PQclear(res);
exit_nicely(conn);
}
strcpy(ic_SQL,ic_LISTEN);
strcat(ic_SQL,ic_Command2);
res = PQexec(conn,ic_SQL);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr,"'%s'Into
Error!\n",ic_Command2);
PQclear(res);
exit_nicely(conn);
}
strcpy(ic_SQL,ic_LISTEN);
strcat(ic_SQL,ic_Command3);
res = PQexec(conn,ic_SQL);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr,"'%s'Into
Error!\n",ic_Command3);
PQclear(res);
exit_nicely(conn);
}
PQclear(res); /* メモリリーク防止のため即に PQclear(PGresult) */
while (1)
{
sleep(1); /*
チェックループ内のウエイト */
PQconsumeInput(conn); /* バックエンド非同期メッセージ取得 */
/* 非同期通知メッセージ有無 */
while ((notify =
PQnotifies(conn)) != NULL)
{
printf("command3.Name'%s',PID='%d' Get From
Backend.",notify->relname,notify->be_pid);
sprintf(ic_256,"%d",notify->be_pid);
strcpy(ic_pidCD,ic_256);
if
((strcmp(notify->relname,ic_Command1)==0))
{
printf("Call.'%s'\n",ic_Command1);
mycommand1(notify->be_pid);
}
if
((strcmp(notify->relname,ic_Command2)==0))
{
printf("Call.'%s'\n",ic_Command2);
mycommand2(notify->be_pid);
}
if
((strcmp(notify->relname,ic_Command3)==0))
{
printf("Call.'%s'\n",ic_Command3);
return;
}
free(notify);
}
}
PQfinish(conn); /* コネクション終了 */
}
/************************************************************************************/
void mycommand1(int ii_pidCD)
{
printf("mycommand1\n");
}
/************************************************************************************/
void mycommand2(int ii_pidCD)
{
printf("mycommand2\n");
}
'notify.c----------------------------------------------------------------------------------------------------
ビルド用
'bd.c----------------------------------------------------------------------------------------------------
#!/bin/bash
#
# echo This Proguram is Build by one.
#
# chmod u+x bd.c 実行権を与える。
# gcc でコンパイルオプション
# -o で実行プログラム名を命名
# -I で'postgres.h'が存在するインクルードディレクトリを指定
# -lpq は、
# -l__ がダイナミック(共有)ライブラリを示し、
# __pq が`PQexec'など`PQ*'のライブラリを示す。
# 予め postgresql-8.2.5.tar.gz を本家から turbolinux11server 自分のディレクトリにダウンロード
# 解凍 tar xvzf postgresql-8.2.5.tar.gz
gcc notify.c -o notify -I /home/dbman/postgresql-8.2.5/src/include -lpq
'bd.c----------------------------------------------------------------------------------------------------
●その他
プログラム開発用のマシンは turbolinux11server 全パッケージ選択でインストールしてください。
(私は、P3B-F.P2,400MHz,RAM.1GB,HDD20G,3Com.3c905+intel,PRO100、故意に遅いマシンを使うことで、
デバッグトレースしやすくしています。HDDを強化すれば大運用システムでも充分耐えます。)
turbolinux11server でプログラム開発するのは大変ですね。
エディタはしょぼいし、操作はWindowsVistaにはとうてい及ばないし、なんて言ってませんか?
これもよく聞くことですが、そうでもないんですよ。
PostgreSQL関連のプログラムしか turbolinux11server に開発しないからGUIは関係ないので、
turbolinux11server 用のgccソースの開発は、無料の「Visual C++ 2008 Express
Edition」でやるんです。
コード記述はこれでなければ仕事する気になれません。VisualシリーズでBASICと共に一元管理できます。
上記ビルド用の「bd.c」も変なファイル名を付けていますが管理しやすくするためです。
プログラムソースを書いたら、FTPで turbolinux11server に送り込み、ターミナルからビルド./bd.cするんです。
( turbolinux11server と WindowsVista の2台を使います。)
ちなみにMakeファイルは作りません、色々拡張していくとMakeファイルの作り込みまで悩まなくてはいけなくなるので、
素直に羅列することでWindowsからの管理を簡単にしています。
なにしろMakeファイルを開発しているのではないのですから。
one.