郵便切手・印紙・売捌所「xxx商店」という店を見かけました。ビジネス街の端っこですが、ほっとした感じがしました。
字面にレトロな響きがあります。店の様子からは切手や葉書の類の販売専門の個人商店のようです。
一昔前は、「大型スーパーが小売店を潰す」というので反対運動が有りました。でも結局は、寂れた商店街が増えてます。
コンビニ効果が大きいのか、経営改善なのか、売り場の大きな酒屋さんは、コンビニに転業する所もあります。
ファストフード店に転業してる小さ目の店もありました。
個人宅レベルの「なんでも屋」「よろず屋」さんを見かけなくなりました。
大資本系列の店が増えると、個人では歯が立たないというのが、現実なんでしょうか。
街角の「たばこ屋」さんが潰れないのが、妙に疑問に思うのです。
駄菓子屋さんや、小さな化粧品屋/薬局など、商売が成立するのか疑問に思える店が、以前はあちこちにありました。
そんな時代が「安定して良い時代だったなぁ」と回顧に浸るのでありました。
深刻な不況で開発仕事自体が減っている昨今ですが、売捌所のような店が残っていて欲しいなぁ。
2009/12/07
ストアードでも例外期待は駄目
前回、例外を期待したコードのコスト高を書きました。
「ストアードにすぺき」とのコメントをいただきました。
ストアードでかいても、例外を期待したコードを書いてしまうと同じですね。
テストしてみました。今回も前回と同様、郵便番号.CSV (約12万行)から 都道府県表(47行)を作るものです。
①例外を期待した場合( してはいけない)
Create PROCEDURE [dbo].[#県名登録_例外] @cd varchar(2), @名称 varchar(10)
AS
BEGIN TRY
insert into J01_都道府県表(都道府県コード,都道府県名称) values (@cd,@名称)
END TRY
BEGIN CATCH
update J01_都道府県表 set 都道府県コード=@cd,都道府県名称=@名称
where 都道府県コード=@cd and 都道府県名称=@名称;
End CATCH
結果:①117 秒
②select文で判断
Create PROCEDURE [dbo].[#県名登録_非例外] @cd varchar(2), @名称 varchar(10)
AS
declare @cnt int;
select @cnt = count(*) from J01_都道府県表 where 都道府県コード=@cd and 都道府県名称=@名称;
if @cnt=0
begin
insert into J01_都道府県表(都道府県コード,都道府県名称) values (@cd,@名称)
end
else
begin
update J01_都道府県表 set 都道府県コード=@cd,都道府県名称=@名称
where 都道府県コード=@cd and 都道府県名称=@名称;
end
結果:②:29秒
③update文の結果で判断
Create PROCEDURE [dbo].[#県名登録_非例外_a] @cd varchar(2), @名称 varchar(10)
AS
declare @cnt int;
update J01_都道府県表 set 都道府県コード=@cd,都道府県名称=@名称 where 都道府県コード=@cd and 都道府県名称=@名称;
set @cnt=@@ROWCOUNT;
if @cnt=0
begin
insert into J01_都道府県表(都道府県コード,都道府県名称) values (@cd,@名称)
end
結果③27秒
まとめると
①117秒
② 29秒
③ 27秒
.net言語(C#/VB)での例外処理した場合の比率は 36:4406で、 122倍のコスト高でしたが、
T-SQLでの比率は 29:117 で 4.03倍なので、言語に比べたら低い結果となりました。
それでも4倍高くつくので、例外を期待するのはやめたほうがよいでしょう。
select文をなくすことで、2秒の差がつきました。削減効果が小さいとはいえ、処理が減るので良いですね。
知恵を絞れば、もっと早くする工夫があるのでしょうね、既存のソースを引用するときは、チェックが必要です。
「ストアードにすぺき」とのコメントをいただきました。
ストアードでかいても、例外を期待したコードを書いてしまうと同じですね。
テストしてみました。今回も前回と同様、郵便番号.CSV (約12万行)から 都道府県表(47行)を作るものです。
①例外を期待した場合( してはいけない)
Create PROCEDURE [dbo].[#県名登録_例外] @cd varchar(2), @名称 varchar(10)
AS
BEGIN TRY
insert into J01_都道府県表(都道府県コード,都道府県名称) values (@cd,@名称)
END TRY
BEGIN CATCH
update J01_都道府県表 set 都道府県コード=@cd,都道府県名称=@名称
where 都道府県コード=@cd and 都道府県名称=@名称;
End CATCH
結果:①117 秒
②select文で判断
Create PROCEDURE [dbo].[#県名登録_非例外] @cd varchar(2), @名称 varchar(10)
AS
declare @cnt int;
select @cnt = count(*) from J01_都道府県表 where 都道府県コード=@cd and 都道府県名称=@名称;
if @cnt=0
begin
insert into J01_都道府県表(都道府県コード,都道府県名称) values (@cd,@名称)
end
else
begin
update J01_都道府県表 set 都道府県コード=@cd,都道府県名称=@名称
where 都道府県コード=@cd and 都道府県名称=@名称;
end
結果:②:29秒
③update文の結果で判断
Create PROCEDURE [dbo].[#県名登録_非例外_a] @cd varchar(2), @名称 varchar(10)
AS
declare @cnt int;
update J01_都道府県表 set 都道府県コード=@cd,都道府県名称=@名称 where 都道府県コード=@cd and 都道府県名称=@名称;
set @cnt=@@ROWCOUNT;
if @cnt=0
begin
insert into J01_都道府県表(都道府県コード,都道府県名称) values (@cd,@名称)
end
結果③27秒
まとめると
①117秒
② 29秒
③ 27秒
.net言語(C#/VB)での例外処理した場合の比率は 36:4406で、 122倍のコスト高でしたが、
T-SQLでの比率は 29:117 で 4.03倍なので、言語に比べたら低い結果となりました。
それでも4倍高くつくので、例外を期待するのはやめたほうがよいでしょう。
select文をなくすことで、2秒の差がつきました。削減効果が小さいとはいえ、処理が減るので良いですね。
知恵を絞れば、もっと早くする工夫があるのでしょうね、既存のソースを引用するときは、チェックが必要です。
2009/12/06
例外に依存するロジックは駄目ですよ
あるシステムの処理が遅いというので、追跡してみました。
元になるデータを順次読み取り、対応するデータが無ければ追加、有れば、更新という単純なものです。
最近のSQL Serverにも Oracle並の Merge文が可能になったので、便利になりました。このシステムでは、自力で処理していました。
遅い原因の一つが次のようなものでした。
while(!eof(元データ))
{
try
{
sql実行(update TABLE set xxx=@xxx , yyy=@yyy where ユニーク条件)
}
catch()
{
sql実行(insert into TABLE (xxx,yyy) values (@xxx,@yyy) )
}
}
業務要件の動作はしますが、駄目でしょう。
(*)これでもソースレビューは合格したらしいので、レビュワーな何をみているのでしょうね。
int cnt = sql実行(Select count(*) from TABLE where ユニーク条件)
if(cnt==0) sql実行( insert into TABLE (xxx,yyy) values (@xxx,@yyy))
else sql実行(update TABLE set xxx=@xxx , yyy=@yyy where ユニーク条件)
とすべきでしょう。(排他処理は省いてます)
駄目だと決めつけてますが、「行儀が悪い」というだけでは、根拠が薄いので、コスト確認してみました。
(例によって)郵便番号CSVデータを用いて、郵便番号CSVから都道府県表を作ります。
元になる郵便番号CSV
自治体コード5桁 都道府県名 市区名
01101,"北海道","札幌市中央区"
……………………
47382,"沖縄県","八重山郡与那国町"
このCSVデータは12万行あります。これを順次読み取り
都道府県表
コード 都道府県名
01 北海道
……………………
27 大阪府
……………………
47 沖縄県
の47行を作ります。
①事前に存在Checkした処理
while(true)
{
string text = sr.ReadLine(); if (text == null) break;
csv分解();
int cnt = sql実行(Select count(*) from TABLE where ユニーク条件)
if(cnt==0) sql実行( insert into TABLE (xxx,yyy) values (@xxx,@yyy))
else sql実行(update TABLE set xxx=@xxx , yyy=@yyy where ユニーク条件)
}
②例外を利用した処理
while(true)
{
string text = sr.ReadLine(); if (text == null) break;
csv分解();
try
{
sql実行(update TABLE set xxx=@xxx , yyy=@yyy where ユニーク条件)
}
catch()
{
sql実行(insert into TABLE (xxx,yyy) values (@xxx,@yyy) )
}
}
結果は
① 36秒
②4406秒
でした。100倍以上の開きがありました。例外が高コストな処理なのがよく判ります。
CSVデータは、[Provider=Microsoft.Jet.OLEDB.4.0;Data Source=xxx] で読み込めば ADO.NETとして処理できます。
そこで [Provider=Microsoft.Jet.OLEDB.4.0;Data Source=xxx] で接続し、
DataTable dt = (SQL実行)"select distinct left( right(str([F1] + 1000000),5),2) , F4 from KEN_ALL.CSV ";
foreach(DataRow dr in dt.Rows)
{
(SQL実行) ( insert into 都道府県表 (code ,名称) values (@code,@名称))
}
で実行しました。③
結果は
③3秒
でした。殆どがDistinct文の処理時間のようです。必要なデータを抽出時に絞ることが重要ですね。(Linqに通じる思想かな)
(*) CSV fileは DataTableに読み込めば、処理が単純になってスッキリ扱えるのでお気に入りなんですが、あまり知られてないのですよねぇ。
都道府県表を作るような処理の場合、重複チェックをDBに依存するのでなく自前で判定すればどうかも、試行しました。④
private List 自前で重複チェック_List = new List();
while(true)
{
string text = sr.ReadLine(); if (text == null) break;
csv分解();
if (!自前で重複チェック_List.Contains(名))
{
自前で重複チェック_List.Add(名);
sql文実行( insert into TABLE( xxx,yyy) values(@xxx,@yyy))
}
結果は
④1秒 (実値0.92秒)
でした。
まとめると(都道府県表をつくるという視点で)
① 36秒
②4406秒
③ 3秒
④ 1秒
最大格差は 4400倍!!。自分もビックリ。「事務データRDBで処理するのがベスト」との声もありますが、このケースのように、事前に対象データの絞り込みは言語で行うほうが良いケースもあります。
実装手段は複数あることが多いので、コスト比較して決定する必要があります。
商売の購入時に合見積もりを取るのと似てますね。
元になるデータを順次読み取り、対応するデータが無ければ追加、有れば、更新という単純なものです。
最近のSQL Serverにも Oracle並の Merge文が可能になったので、便利になりました。このシステムでは、自力で処理していました。
遅い原因の一つが次のようなものでした。
while(!eof(元データ))
{
try
{
sql実行(update TABLE set xxx=@xxx , yyy=@yyy where ユニーク条件)
}
catch()
{
sql実行(insert into TABLE (xxx,yyy) values (@xxx,@yyy) )
}
}
業務要件の動作はしますが、駄目でしょう。
(*)これでもソースレビューは合格したらしいので、レビュワーな何をみているのでしょうね。
int cnt = sql実行(Select count(*) from TABLE where ユニーク条件)
if(cnt==0) sql実行( insert into TABLE (xxx,yyy) values (@xxx,@yyy))
else sql実行(update TABLE set xxx=@xxx , yyy=@yyy where ユニーク条件)
とすべきでしょう。(排他処理は省いてます)
駄目だと決めつけてますが、「行儀が悪い」というだけでは、根拠が薄いので、コスト確認してみました。
(例によって)郵便番号CSVデータを用いて、郵便番号CSVから都道府県表を作ります。
元になる郵便番号CSV
自治体コード5桁 都道府県名 市区名
01101,"北海道","札幌市中央区"
……………………
47382,"沖縄県","八重山郡与那国町"
このCSVデータは12万行あります。これを順次読み取り
都道府県表
コード 都道府県名
01 北海道
……………………
27 大阪府
……………………
47 沖縄県
の47行を作ります。
①事前に存在Checkした処理
while(true)
{
string text = sr.ReadLine(); if (text == null) break;
csv分解();
int cnt = sql実行(Select count(*) from TABLE where ユニーク条件)
if(cnt==0) sql実行( insert into TABLE (xxx,yyy) values (@xxx,@yyy))
else sql実行(update TABLE set xxx=@xxx , yyy=@yyy where ユニーク条件)
}
②例外を利用した処理
while(true)
{
string text = sr.ReadLine(); if (text == null) break;
csv分解();
try
{
sql実行(update TABLE set xxx=@xxx , yyy=@yyy where ユニーク条件)
}
catch()
{
sql実行(insert into TABLE (xxx,yyy) values (@xxx,@yyy) )
}
}
結果は
① 36秒
②4406秒
でした。100倍以上の開きがありました。例外が高コストな処理なのがよく判ります。
CSVデータは、[Provider=Microsoft.Jet.OLEDB.4.0;Data Source=xxx] で読み込めば ADO.NETとして処理できます。
そこで [Provider=Microsoft.Jet.OLEDB.4.0;Data Source=xxx] で接続し、
DataTable dt = (SQL実行)"select distinct left( right(str([F1] + 1000000),5),2) , F4 from KEN_ALL.CSV ";
foreach(DataRow dr in dt.Rows)
{
(SQL実行) ( insert into 都道府県表 (code ,名称) values (@code,@名称))
}
で実行しました。③
結果は
③3秒
でした。殆どがDistinct文の処理時間のようです。必要なデータを抽出時に絞ることが重要ですね。(Linqに通じる思想かな)
(*) CSV fileは DataTableに読み込めば、処理が単純になってスッキリ扱えるのでお気に入りなんですが、あまり知られてないのですよねぇ。
都道府県表を作るような処理の場合、重複チェックをDBに依存するのでなく自前で判定すればどうかも、試行しました。④
private List
while(true)
{
string text = sr.ReadLine(); if (text == null) break;
csv分解();
if (!自前で重複チェック_List.Contains(名))
{
自前で重複チェック_List.Add(名);
sql文実行( insert into TABLE( xxx,yyy) values(@xxx,@yyy))
}
結果は
④1秒 (実値0.92秒)
でした。
まとめると(都道府県表をつくるという視点で)
① 36秒
②4406秒
③ 3秒
④ 1秒
最大格差は 4400倍!!。自分もビックリ。「事務データRDBで処理するのがベスト」との声もありますが、このケースのように、事前に対象データの絞り込みは言語で行うほうが良いケースもあります。
実装手段は複数あることが多いので、コスト比較して決定する必要があります。
商売の購入時に合見積もりを取るのと似てますね。
2009/12/04
携帯サイトアプリの画面遷移
携帯サイトはJavascriptもAJAXもCookieも使えません。
画面遷移に使えるコントロールは<&a href=''/> か の二種類程度しかありません。
{更新][削除}[戻る]など複数の分岐をボタンで行うとき、複数のsubmitボタンを配置することになります。
submitキーの反応は、pagePostBackとして自画面で受けます。そのとき、画面情報は Page.Request[] で取得できます。
幸せなことに、submitボタンが複数個あっても、押されたボタンのみが送られてきます。
(*)仕様的にそうするしかなったのでしょうが、画面情報を取得するという面では、Submitコントロールは別扱いなんでしょうね。
押されたsubmitキーの判別は、Page.Request[]を順次スキャンして、コントロール.Nameを調べるのが正攻法でしょう。
画面仕様によっては、データの量に応じてn個のsubmitキーを配置することもあります。
その際は、レコードIDをコントロール名に含めるなど、小技をつかって小細工することになります。
うーん。エレガントでないですね。なんかスマートな方法がないものでしょうか。
画面遷移に使えるコントロールは<&a href=''/> か の二種類程度しかありません。
{更新][削除}[戻る]など複数の分岐をボタンで行うとき、複数のsubmitボタンを配置することになります。
submitキーの反応は、pagePostBackとして自画面で受けます。そのとき、画面情報は Page.Request[] で取得できます。
幸せなことに、submitボタンが複数個あっても、押されたボタンのみが送られてきます。
(*)仕様的にそうするしかなったのでしょうが、画面情報を取得するという面では、Submitコントロールは別扱いなんでしょうね。
押されたsubmitキーの判別は、Page.Request[]を順次スキャンして、コントロール.Nameを調べるのが正攻法でしょう。
画面仕様によっては、データの量に応じてn個のsubmitキーを配置することもあります。
その際は、レコードIDをコントロール名に含めるなど、小技をつかって小細工することになります。
うーん。エレガントでないですね。なんかスマートな方法がないものでしょうか。
2009/12/03
トイレットペーパー持ち出し禁止?
最近、雑居ビルのトイレで、このような張り紙を見かけます。こないだは、
「 トイレットペーパーは持ち出さないでください。あなたの行為は誰かが見ています。後々後悔しないためにも。」
のような、訓示めいた張り紙もありました。
見かける頻度が高くなっているのは、持ち帰る人が増えたわけか。節約の為だとしたら、セコすぎますね。
以前は(電車の)駅トイレは紙は有料でしたが、最近は標準で設置しています。結構な費用が必要だと聞きます。
こちらのほうが、持ち帰る被害が、多そうですが、どうなんでしょうね。
持ち出す人は、ほかに使用目的があるのでしょうか。
トイレにゴミ袋を放置して、ゴミ処理する人もいるとか。
気が滅入る時代なんだなぁ。
「 トイレットペーパーは持ち出さないでください。あなたの行為は誰かが見ています。後々後悔しないためにも。」
のような、訓示めいた張り紙もありました。
見かける頻度が高くなっているのは、持ち帰る人が増えたわけか。節約の為だとしたら、セコすぎますね。
以前は(電車の)駅トイレは紙は有料でしたが、最近は標準で設置しています。結構な費用が必要だと聞きます。
こちらのほうが、持ち帰る被害が、多そうですが、どうなんでしょうね。
持ち出す人は、ほかに使用目的があるのでしょうか。
トイレにゴミ袋を放置して、ゴミ処理する人もいるとか。
気が滅入る時代なんだなぁ。
2009/12/02
3穴パンチ
(今は改善されているかもしれませんが)
IBM関係の書類は3つの穴が空いている書類が多かったです。
日本以外の会社では、3穴バインダーが多いからだと聞きました。でも、此処は日本です。
(参考) http://www2.ocn.ne.jp/~hasamaya/jimuyouhin/panch/4panch.htm
一般の文具屋さんには、3穴バインダーは置いてません。パイプ式も殆どが二穴です。
西洋で主流とされる3穴式が日本で普及しなかった理由は判りません。日本での主流は二穴です。
その文化背景を考えると、外資系企業でも、配布資料は二穴式にして欲しいです。
3穴パンチも需要が少ないため、結構高価なものになってます。
紙のサイズも、欧米ではA3/A4/A5が主流だそうです。B3/B4/B5は日本ローカル仕様のようです。
明治期は舶来崇拝だと言われますが、日本規格を貫いて独自色を出した部分もあるようですね。
それは、良いことだと思います。文化といえますね。「郷にいれば郷に従う」でしょう。外資系企業が母国文化を持ち込んで、不毛な摩擦が生じると、双方にとってマイナスですね。
文房具一つで、不満を感じるので、感情は難しいものです。
IBM関係の書類は3つの穴が空いている書類が多かったです。
日本以外の会社では、3穴バインダーが多いからだと聞きました。でも、此処は日本です。
(参考) http://www2.ocn.ne.jp/~hasamaya/jimuyouhin/panch/4panch.htm
一般の文具屋さんには、3穴バインダーは置いてません。パイプ式も殆どが二穴です。
西洋で主流とされる3穴式が日本で普及しなかった理由は判りません。日本での主流は二穴です。
その文化背景を考えると、外資系企業でも、配布資料は二穴式にして欲しいです。
3穴パンチも需要が少ないため、結構高価なものになってます。
紙のサイズも、欧米ではA3/A4/A5が主流だそうです。B3/B4/B5は日本ローカル仕様のようです。
明治期は舶来崇拝だと言われますが、日本規格を貫いて独自色を出した部分もあるようですね。
それは、良いことだと思います。文化といえますね。「郷にいれば郷に従う」でしょう。外資系企業が母国文化を持ち込んで、不毛な摩擦が生じると、双方にとってマイナスですね。
文房具一つで、不満を感じるので、感情は難しいものです。
2009/12/01
坂の上の雲
大河ドラマが11月で最終回になったので、変だなぁと思っていたら、足かけ三年に渡るドラマが始まるとか。
1年を通して観続けるのは、辛いです。ビデオにとっておいても、観ないままお蔵入りすることも多々あります。
筋書きの展開が早いときは、間が飛ぶとストーリーがワケワカになったりします。
三ヶ月単位のドラマが主流になっている昨今で、3年スケールのドラマで勝負するとは、さすがNHKだなぁ。と思ったしだい。
司馬遼太郎史観の是非は、ともかく、ドラマとして楽しめそうでした。でも2部、3部が1年後というのは。
そのころは、1部の内容は忘却しているだろうな。スパンが長すぎる希ガス。
1年を通して観続けるのは、辛いです。ビデオにとっておいても、観ないままお蔵入りすることも多々あります。
筋書きの展開が早いときは、間が飛ぶとストーリーがワケワカになったりします。
三ヶ月単位のドラマが主流になっている昨今で、3年スケールのドラマで勝負するとは、さすがNHKだなぁ。と思ったしだい。
司馬遼太郎史観の是非は、ともかく、ドラマとして楽しめそうでした。でも2部、3部が1年後というのは。
そのころは、1部の内容は忘却しているだろうな。スパンが長すぎる希ガス。
登録:
投稿 (Atom)