2017年11月13日月曜日

MySQLのチューニング(JOIN編)

おそらくオプティマイザの挙動が安定しないことが起因で、今まで問題なく動作していたクエリがものすごく遅くなるという事象に遭遇しました。
結果、「ばらし」て組み直すことで解消したのですがその一部始終で技術要素を色々調べられたのでメモしておきます。

やったことの結果要約

・5つあるJOIN句のなかにサブクエリが2つあったので、先行してTemporaryTableへ吐き出すようにした
 →合わせてその時にIndexも貼る
・ベースとして結合したい表をFROMの後へ置き、そのあとは結合しやすい順で並べた。
 →特に意味はないという記事もあったが念のため。元は「ほしい情報」をベースで置いていた。
・結合の条件のなかで、左に今まで出てきている項目、右が対象項目という順とした。
 →オプティマイザに効果があるとの情報
・結果、2分かかっても終わらなかったものが、6秒。これでOKとしました。

実施1)Temporary Tableを使い処理を分割

元々1クエリだったものを、分割して、事前にTemporaryを作成、そのあとにクエリでTemporaryから読むという分割をしました。

【Temporary Table作成の構文】
 CREATE TEMPORARY TABLE temptablename
(INDEX idx_temporary (a,b)) ENGINE=MEMORY
SELECT a,b,c,d,e from table1
今回はSSD環境のDBだったのでMyISAMでも良いのですが、メモリへの展開と指定しました。tmp_table_sizeの設定に依存しますが、今回は許容範囲内なので問題なし。
構文にはフィールド名、型名を指定する方法もありますが、今回はベース表のフィールド名、型をそのまま引き継ぐ形で作ればよく、省略して記載しています。

実施2)ベースの表を変える

対象レコードが少ない表をベース表とし、INNER JOINで結合していきました。
これは今まであまり気にしていませんでしたが、オプティマイザの仕組みを考えると理にかなっている方法だと思います。

実施3)結合の構文の左右を意識する

例文)
select tbl1.a , tbl2.cc from tbl1 inner join tbl2 on tbl1.a = tbl2.a
通常無意識的にメイン表を左、結合対象を右にしていましたが、今回は一部の結合条件で左右が逆でした。

ダメな例文)
select tbl1.a , tbl2.cc from tbl1 inner join tbl2 on tbl2.a = tbl1.a
これもオプティマイザの解釈を考慮すれば当然なのでしょうが、結合したい基本を左に置くことを意識し、全体を調整しました。
→結合表が多くなってきた時に無意識に間違いそうな気がします。

実施4)Temporary Tableにインデックス

これは「ひょっとしたら」で追加したのですが、効果が劇的でした。
Temporary(今回は2つ)はそれぞれUNIQUEなので結合項目としてはすべて使ってます。※先の例で言うとa,b,c,d,eのすべてが結合条件。
それにもかかわらず、aとb(抽出元表:table1のPrimary)にインデックスを貼ったことで
使ってくれて、速度も向上したのです。
知識ある人からしたら「当然だよ」かもしれませんが結果には驚きました。

その他)STRAIGHT_JOIN

結局試していないのですが、[STRAIGHT_JOIN]キーワードを使うと、JOINの順番を強制することができるようです。

2017年10月8日日曜日

JasperReport (IReport)でHH:mm形式の時間を合計する

技術Tipsです

〇要件

グループ計で時間を合計したい。
 ex) 勤務時間のような日別の時間で、グループ計を取る

〇前提

各レコードにはHH:mm形式のデータがある。 ex) 12:30
 定義名はF_HHMMとする

〇実装 (IReportのバージョンは4.0.2)

1)variablesで分に置き換えて保持しておく。
Name:V_HHMM
 Variable Class : java.lang.Integer
   Calculation : Sum
 Reset type:Group
 Reset group:対象のグループ名
 Increment type:none
 Variable Expression:
$F{F_HHMM}.equals(null) ? 0 : new Double(new Double(new Double($F{F_HHMM}.substring(0,2)) * 60) + new Double($F{F_HHMM}.substring(3,5)))

2)レコード出力対象のフィールドにてFieldExpressionを定義

$F{V_HHMM}.equals(null)?null:(((new Integer($F{V_HHMM}) / 60).toString().replace('.',':').split(':')[0])  + ':' + ((new Integer($F{V_HHMM}) % 60).toString().length()==1?('0'+(new Integer($F{V_HHMM}) % 60)):(new Integer($F{V_HHMM}) % 60)))

2017年10月5日木曜日

Illustrator CS2 でIMEが利用できない (事象のみ。未解決)

最近は社内SEもしております。

Illustrator CS2を使って名刺など作りたいという要望があり、個人パソコンへ
インストールするのも後で面倒そうなので、新規にWindows7環境を構築して
Illustrator CS2をインストールしたところ、IMEが使えない。と。。。

現象の詳細

・Illustrator CS2を起動して、テキストエリアなどで半角/全角キーを押しても入力モードが切り替わらない
・アプリを終了 → IMEのバーをタスクバーへ入れてアプリ起動 するとアプリの起動時にIMEのバーが消える (この時点でおかしいよね。。。と)
・他のアプリを起動して利用してみると、IMEのバーは表示される。
・いわゆる「再起動すれば直る」を期待したが、それでもNG

まずは調べてみた

1)Windows7ではCS2に対応していない
2)IME2010をインストールすると直るかもね。
3)キーボードショートカットのバッティングが原因では?

試してみた

1)互換性モードでアプリケーションを起動 → 解消せず
2)IME2010をインストール → 解消せず
3)「キーボードまたは入力方法の変更」から「キーボードの変更」→「詳細なキー設定」→「入力言語を切り替える」を「左shift+Alt」から「なし」へ変更 →解消せず

想定外の挙動

Illustratorが標準で持つショートカットキーも、一部使えない(ズームなど)
結局のところ、未サポート -> キーボード操作の一部に不良 という現象は綺麗に解決できそうにありませんでした。

結果

CS2の利用はあきらめました。
Illustrator CS3があったのでCS2をアンインストール後、CS3をインストール。無事に動くことを確認できました。

2017年1月19日木曜日

VBAマクロを利用した繰り返し処理

業務でパソコンを利用している以上、エクセルは日常的に使います。

Excelでの印刷関連の設定は複数シートまとめて行う事ができないので
マクロで記録して、ちょこっとVBAを書いて連続処理することで手抜きを実現しています。

手順の概略

1.開発タブ→マクロの記録 で、行いたい印刷設定を行う。
 →開発タブが出ていない場合にはググって調べてください。設定で出せます。
2.以下のテンプレコードをVBAに貼り付ける。
3.テンプレコードを実行する

テンプレートコード(そのまま貼り付けて1行だけ修正)


Public Sub ExecuteAllSheets()
    
    Dim ws As Worksheet
    
    '高速化対応:再描画、都度計算を無効とする
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    'エラーハンドリングの開始
    On Error GoTo ErrorHandler
    
    '全シートに対して繰り返し処理を行う
    For Each ws In ThisWorkbook.Worksheets
        ws.Select
        Call Macro1   '(ここを変更)ここで繰り返し行いたい処理を指定
    Next
    
    'エラーハンドリングをやめてプログラム終了処理へ
    On Error GoTo 0
    GoTo Program_Exit

ErrorHandler:
    MsgBox "エラーが発生しました" & vbCrLf & _
            "No." & Err.Number & vbCrLf & _
            "Message : " & Err.Description, vbExclamation, ""

Program_Exit:

    '高速化対応:解除
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationManual

End Sub

【補足】

・プリンタ関連の処理を記憶すると、自働で作成されたコード中に以下が記録されるケースがあります。
 →ActiveWindow.SelectedSheets.PrintPreview
 これが記録されていると、処理が連続で行われません。(プレビューで止まる)
・余白調整、ヘッダフッタの一括設定等々、画面でできることはすべて処理できます。
 →どこで何ができるかは自動作成されたコードを見て判断してください。