DBマガジン、休刊
ニッチと言えばニッチなジャンルの雑誌だっただけに仕方ないですが、良く読んでた雑誌が消えていくのは、なんだか寂しいです。
一応RDBMS屋のつもりだった昔、データベーススペシャリストの試験に受かるまで、1、2年くらい定期購読してたんですが、だんだんとWEBな人になってから、最近は読んでませんでした。
自分の興味の対象がデータそのものからサービスに向かっちゃった事で、面白く読めなくなってきたんですね。
関係者の方々はお疲れ様でした。
ニッチと言えばニッチなジャンルの雑誌だっただけに仕方ないですが、良く読んでた雑誌が消えていくのは、なんだか寂しいです。
一応RDBMS屋のつもりだった昔、データベーススペシャリストの試験に受かるまで、1、2年くらい定期購読してたんですが、だんだんとWEBな人になってから、最近は読んでませんでした。
自分の興味の対象がデータそのものからサービスに向かっちゃった事で、面白く読めなくなってきたんですね。
関係者の方々はお疲れ様でした。
今まで色んなデータベース管理ツール(特に無償のん)を使ってきたけど、使用頻度といい、期間といい、圧倒的にこれがナンバーワン。
ワタシにとって手放せない理由は、さくっとExcelでテーブル定義書を出力してくれる所。
全体的にすんごく動作が軽い事もイイし、スプレッドシート感覚でデータ操作もできる。
SQL文の実行もできる。OracleでいうObject Browserの様なもの。
残念ながら、2002年からメンテナンスはされていない様ですが、ODBCドライバのインストールと設定さえしてあれば、今でも使えます。
ODBCでイケるから、MySQLだろうがPostgreSQLだろうが、SQL Serverも、DB2も、勿論Oracleも使えます。
多少ならお金払いますから、是非メンテナンスを継続して頂きたい。
Windowsちょっとイイツール紹介シリーズその1でした。
Spring Framework から Oracle の CLOB や BLOG を扱う事がある。
Oracle9i の頃から、LOB にはちょっと苦労させられた。
9iの頃のJDBCドライバ(Thin)では、文字数の制約で色々めんどくさかったけど、
10g以降のJDBCドライバでは、いい感じに変換してくれるのか、CLOBフィールドの参照系ならVARCHAR感覚でコーディングできてた。
でも、更新系では手抜きが通じない。
8000バイト位(多分8192バイト)を超える文字列をInsert/Updagteすると、文字列が一部欠落してしまう。
こっちはいい感じに変換してくれない。
仕方ないから、LobHandlerを使ってちゃんと書いた(つもり)。
Spring は未だに 1.2 を使ってマス。
Sprint 2系でも、いっしょじゃないだろうか。
設定はこんな感じで、lobHanderをインジェクションする。
<bean id=”lobHandler” class=”org.springframework.jdbc.support.lob.OracleLobHandler”>
<property name=”nativeJdbcExtractor” ref=”nativeJdbcExtractor”/>
</bean><bean id=”nativeJdbcExtractor” class=”org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor”/>
<bean id=”abstractDao” abstract=”true”>
<property name=”dataSource”>
<ref bean=”dataSource” />
</property>
</bean><bean id=”hogeDao” parent=”abstractDao”
class=”your.package.dao.HogeDaoImpl” >
<property name=”lobHandler”>
<ref bean=”lobHandler” />
</property>
</bean>
org.springframework.jdbc.object.SqlUpdate を継承したクラスを作る。
Types は CLOBに。後は特に留意点なし。
package your.package.dao.sql;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import javax.sql.DataSource;import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.SqlUpdate;public class Create extends SqlUpdate {
public Create(DataSource ds) {
super(ds, QUERY);
super.declareParameter(new SqlParameter(Types.INTEGER)); // ID
super.declareParameter(new SqlParameter(Types.CLOB)); // Clob Data
compile();
}private static final String QUERY = “INSERT INTO Table (ID, CLOBFIELD) VALUES ( ?,? )”;
んで、org.springframework.jdbc.core.support.JdbcDaoSupport を継承して、さっきのSqlUpdateクラスを使う。
DIしたlobHandler を使って、 SqlLobValueを生成してあげる。
package your.package.dao.sql;
public class HogeDaoImpl extends JdbcDaoSupport {
public HogeDaoImpl() {
super();
}private LobHandler lobHandler_;
public void setLobHandler(LobHandler lobHandler) {
lobHandler_ = lobHandler;
}public void save(Object entityBean) {
BeanOfTable bean = (BeanOfTable) entityBean;
SqlLobValue clobField = new SqlLobValue(bean.getBody(), lobHandler_);
String id = bean.getId();
Create create = new Create(getDataSource());
create.update(new Object[]{ id, clobField });
}
Spring Framework の JdbcTemplate を使ってて、こんなんでました。
java.sql.SQLException: 列索引が無効です。
[commons-dbutils] エラー:列索引が無効です。 – メモ!メモ! – Yahoo!ブログ
によると、
PreparedStatementのプレースホルダの数と、設定しているパラメータの数が合っていない。
らしい。
が、数は有っている。
散々悩んだ挙句、ResultSetのgetXX の引数が、途中で間違ってた。
こんな感じ。
bean.setValue1(rs.getString(1)); bean.setValue2(rs.getString(2)); bean.setValue8(rs.getString(8)); bean.setValue4(rs.getString(4)); bean.setValue5(rs.getString(5)); bean.setValue6(rs.getString(6));
実際は、列の数が200以上ある様なケースだったので、なかなか判らなかったのだ。
自戒の意味を込めて、書いておこう。
SQL Server 2000のロックは、動的にロック方法を自動判断して行われる。
行ロック・ページロック・DBロック
上記のチューニングとしてMS SQLでは”分離レベル”の設定 が4つある。
下に行くほどデータの整合性が上がるが、デッドロックが起こりやすくなる。
OLTPの場合、余程大勢でInsert、Updateをしない限り、デフォルトでいいんじゃないかと思う。
トランザクションを使用する場合は、明示的に 3) を選択 (後述) する場合もあるかも知れない。
但し、トランザクションは短めに。
1) READ UNCOMMIITTED
ユルユル。ダーティリード可能
2) READ COMMITTED
コミット済み読み取り (SQL Server の既定の分離レベル)
3) REPEATABLE READ
4) SERIALIZABLE
直列化 (各トランザクションが完全に分離される最高の分離レベル)
ロックは明示的にもできる。ロックヒントと呼ばれるモノをSQLステートメントに挿入ればいい。
SELECT * FROM TABLE_NAME WITH (ROWLOCK) WHERE FIELD_NAME = 'hoge'
WITHのとこのロック種類はこんなにある。
ロックが競合した時のタイムアウト設定があるらしい。
SET LOCK_TIMEOUT [timeout_period(ミリ秒単位)]デフォルト0ミリ秒
と言う事は、トランザクションが失敗した時の処理をキチンと実装しなければ(ロールバック->コネクトクローズ)、タイムアウトまで待ちっぱなしになると言う事になると言う事だろうか。
ロックの状況は、エンタープライズマネージャで確認できる。ストアドプロシージャ(sp_lock)、master.syslockinfoテーブルでも確認できる。
参考サイト
ZDNet SQL Serverのデットロックを防ぎ同時実行性を向上させよう
トランザクション分離レベルの選択とデッドロックの問題~ SQL Server 2000 における Web アプリケーション開発 ~
RDBMSをスケールさせる為に、データを垂直分割したいときがある。
それに備えて、DB設計時から垂直分割するのは是か非か。
SQL Serverは1つのインスタンスに複数のデータベースが作れる。
貧乏なウチは、1つの物理サーバかつインスタンスで、複数のデータベースを作って、データを垂直分割し、アプリケーション側で何の工夫もせずに、SQLだけで検索できなくもない。
例えば、2億レコードの単一DB と、 10万レコードの200個のデータベースとで、どれ位のパフォーマンスの差がでるだろう。
一般的に、テーブルが分かれると発行するSQL文が増える為、パフォーマンスが低下するのだけど、設計とSQLの作りにもよるし、実際に検証しなければわからない。
時間があれば一度検証してみたい。
最低でも、データベースファイルとトランザクションログファイルは物理的に分けたい。
SANにデータベースファイル、ローカルHDDにトランザクションログファイルとか。
ある。BOL参照。インストール時にカスタムを選択し、開発ツールを選択すると、スクリプトのサンプルもインストールされる。
MS SQL Serverの接続方法には色々あるが、PHPでの使用となると、ODBC関数の使用もしくはMS SQL関数の使用の2つが用意されている。
下記2つのパフォーマンスの善し悪しは、比較検証して見ないと分からない。
1)MS SQL関数
MS SQL関数は、MS SQLクライアントツール”ntwdblib.dll”を必要とする。
このモジュールは、DB-Libraryと呼ばれる呼び出しインターフェースで、MS SQL Server6.5の頃の古いAPIである。下位互換の為に用意されているようで、MS SQL Server2000で用意された新機能を使う事が出来ないらしい。Unicodeにも非対応である(非対応の意味が良く分からないが)。
2)ODBC関数
ODBC3.7以上では、Unicodeをサポートするようだ。(要検証)
正確には、MDAC 2.1以上 または SQL Server ODBC ドライバ (バージョン 3.70.0623 以降) または OLEDB プロバイダ (バージョン 7.01.0623 以降(MS KB JP234748)。
MS SQL Serverをインストールすると、MDAC2.6がインストールされるようだ。