harupiyoの日記 RSSフィード

 

2014-06-28 MySQL 5.6.5 からのMATERIALIZED

[][] MySQL 5.6.5 から導入されたクエリ最適化戦略のMATERIALIZED について  MySQL 5.6.5 から導入されたクエリ最適化戦略のMATERIALIZED についてを含むブックマーク

新しいMySQL ではEXPLAIN にMATERIALIZED が出てくるようになったのに気付きました。

|  2 | MATERIALIZED | city   | ALL    | CountryCode   | NULL   | NULL    | NULL | 4188 | Using where |

なんじゃこりゃ。

サブクエリ最適化の一種

http://dev.mysql.com/doc/refman/5.6/en/explain-output.html

EXPLAIN で表示されるこれはMaterialized subquery のことだと書いてあります。

http://dev.mysql.com/doc/refman/5.6/en/subquery-optimization.html#subquery-materialization

んで、Materialized subquery はサブクエリ最適化の一種とのこと。

今日は、ここの記事に書いてあることを元に、具体例も付けて紹介してみたいと思います。

これまでの方式

これまでは

SELECT * FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2 WHERE where_condition);

を実行すると、以下のように絞り込み条件t1.a = t2.b を追加する書き換えが行われて、サブクエリ側で全件取得しなくてもいいような工夫がなされていました。

SELECT * FROM t1 WHERE EXISTS (SELECT t2.b FROM t2 WHERE where_condition AND t1.a=t2.b);

本当にそうなるか、試してみます。

なおMySQL のドキュメントページで配布されているサンプルデータベースを元に実験します。

http://dev.mysql.com/doc/index-other.html

例)人口が100万人以上の都市を持つ国を取得. MySQL 5.5.27 で確認

mysql> EXPLAIN SELECT * FROM Country
    -> WHERE Code IN (SELECT CountryCode FROM City WHERE Population > 1000000);
+----+--------------------+---------+----------------+---------------+-------------+---------+------+------+-------------+
| id | select_type        | table   | type           | possible_keys | key         | key_len | ref  | rows | Extra       |
+----+--------------------+---------+----------------+---------------+-------------+---------+------+------+-------------+
|  1 | PRIMARY            | Country | ALL            | NULL          | NULL        | NULL    | NULL |  245 | Using where |
|  2 | DEPENDENT SUBQUERY | City    | index_subquery | CountryCode   | CountryCode | 3       | func |    8 | Using where |
+----+--------------------+---------+----------------+---------------+-------------+---------+------+------+-------------+
2 rows in set (0.08 sec)

City テーブルはインデックスを使った検索となっているので、明らかに

mysql> EXPLAIN SELECT * FROM Country
    -> WHERE EXISTS (SELECT CountryCode FROM City WHERE Population > 1000000 AND Country.Code = City.CountryCode);

のようにクエリが書き直された時の動きになっています。

今回はストレージエンジンから取得する行数の見積もりは245 + (245 * 8) = 約2250行ですね。

MySQL 5.6.5 からのMATERIALIZED

さて、ドキュメントの内容に戻ると、MySQL 5.6.5 からは最適化戦略として"サブクエリの実体化(Materialize)" が追加されました。

何が実体化なのかというと、サブクエリを実行するのに有利になるようなテンポラリテーブルが作られることを指しており、通常はメモリ上にハッシュインデックスが作られるようです。

この方式のメリットは、

  • クエリの書き換え不要
  • 再度サブクエリの実行が必要な時には、テンポラリテーブルを参照するだけでよい。これはインデックスを使って高速に動作。

です。

例)先ほどと同じ例をMySQL 5.6.16 で確認

+----+--------------+-------------+--------+---------------+------------+---------+--------------------+------+-------------+
| id | select_type  | table       | type   | possible_keys | key        | key_len | ref                | rows | Extra       |
+----+--------------+-------------+--------+---------------+------------+---------+--------------------+------+-------------+
|  1 | SIMPLE       | country     | ALL    | PRIMARY       | NULL       | NULL    | NULL               |  239 | Using where |
|  1 | SIMPLE       | <subquery2> | eq_ref | <auto_key>    | <auto_key> | 3       | world.country.Code |    1 | NULL        |
|  2 | MATERIALIZED | city        | ALL    | CountryCode   | NULL       | NULL    | NULL               | 4188 | Using where |
+----+--------------+-------------+--------+---------------+------------+---------+--------------------+------+-------------+
3 rows in set (0.00 sec)

ばっちりMATERIALIZED と出ています。

このEXPLAIN からは、まずid=2 のCity テーブルが全件スキャンされテンポラリテーブルとして実体化されたあとで、id=1 のcountry、<subquery2>(これがテンポラリテーブル) がJOIN(NLJ) を構成するというように読めます。


なおNLJ など、そもそもEXPLAIN については「漢のコンピュータ道」の記事を参照になさってください。(いつも大変お世話になっております)

http://nippondanji.blogspot.jp/2009/03/mysqlexplain.html


最初に4188件を全件スキャンしてインデックス付きのテンポラリテーブルを作る処理がいかほどのものか気になりますが、一度それができてしまえば、クエリ本体の処理に必要なアクセス行数の見積もりは 239 + (239 * 1)...いえ、<subquery2> へはインメモリのハッシュインデックスで超高速に動くはずですからほぼ無視できる形で、239 + (239 * 0) = 239行 の見積もりとなるのだと考えています。

2012-08-04 [Perl][正規表現] alt 指定のないimg タグを洗い出す方法

[Perl][正規表現][NoEditor(鬼車)] alt 指定のないimg タグを洗い出す方法  [Perl][正規表現][NoEditor(鬼車)] alt 指定のないimg タグを洗い出す方法を含むブックマーク

こんにちは、harupiyo です。

正規表現を書く時に、中にalt を含まないimg タグを探すにはどうしたらよいのだろう?と思って調べてみました。

Perl の場合と、正規表現ライブラリ"鬼車" を使っているNoEditor の場合で試してみています。


詳説 正規表現 第3版

詳説 正規表現 第3版

(ひさしぶりに読んだ...)


正規表現のパターンの中に、(?!alt)と記述すると、altを含まない場合という指定ができます。

Perl の場合

#!/usr/bin/perl

# 検索対象文字列
$str = <<EOF;
<img src="test.jpg"><img src="test2.jpg" alt="hello"><img src="test3.jpg">
<img src="test.jpg" alt="">                       
<img src="test.jpg" alt="test">
<img src="test.jpg" ALT="test">
EOF

$regexp = qr/
    (
        <img
            (?!         # 先読み条件指定開始,
                [^>]*       # > 以外の文字が続いて,
                alt="       # alt=" が来て
                [^"]        # すぐに" で閉じるのでない場合
            )           # はマッチ対象から除外する
            [^>]*       # 除外しない場合は、<img のあとに続く
        >               # > までの間の文字を
    )                   # $1 に保存する
/ix;                    # Option: i ... 大文字小文字を区別しない           
                        #       : x ... 正規表現中に# でのコメントをゆるす

# 上の正規表現は、こう一行で書いたのと同じです(どちらでも動きます)
$regexp = qr/(<img(?![^>]*alt="[^"])[^>]*>)/ix;                 

# マッチするパターンを全て表示(洗い出し)
while( $str =~ m/$regexp/g ){
    print $1 . "\n";
}

__END__
実行結果:
<img src="test.jpg">
<img src="test3.jpg">
<img src="test.jpg" alt="">

上のPerl のコードでは、正規表現にコメントを付けておきました。

NoEditor の場合

NoEditor(あるいはNoEditor 付属のYokkaGrep) でも同じことが実行できました。

f:id:harupiyo:20120804150526p:image


以上、ご参考になさってください。

2010-05-31 Eclipse でworkspace の存在が悪さをすることがある件

Eclipse でworkspace の存在が悪さをすることがある件 Eclipse でworkspace の存在が悪さをすることがある件を含むブックマーク

一般的な状況ではないでしょうが、こんなことがあったよということでメモ。

Eclipse のplugins フォルダの中の、不要物を削除しよう…といじっているうちに、肝心のSubversive が動かなくなってしまいました。

※こんなエラーが...SVN Repository の画面を開くところで

Could not create the view: Plug-in org.eclipse.team.svn.ui was unable to load class org.eclipse.team.svn.ui.repository.browser.RepositoryBrowser.

こわいよ!


どうしようもなくなってしまったので、まっさらな状態から始めようと新規にEclipseインストールし、そこにSubversive プラグインインストールして見てもやっぱりエラーになってしまう。

Windowsレジストリに登録された情報が悪さをしているのかな?と思って、

eclipse.exe -clean

として実行してみるもやはり同じところでエラー。

そこまで来てEclipse の起動時に、旧来のworkspace を指していたことを思い出し、別のところを指すようにしてみたところようやくSVN Repository がちゃんと開くようになり、問題が解決できました。

教訓

改めてworkspace を見ると、その中の.metadata\.plugins フォルダの中で各プラグインの情報を持っているようで、勝手にeclipse\plugins 下をいじってはダメだったかもしれませんね。

また、Eclipse はworkspace 下に設定情報を持っているのだ!ということでメモ。

2010-05-17 [perl] 繰り返し演算子x のこんな動き

[perl] 繰り返し演算子x のこんな動き  [perl] 繰り返し演算子x のこんな動きを含むブックマーク

さあて、クイズです。

#!/usr/bin/env perl

sub counter_gen{
	my $c = 1;
	return sub { return $c++; }
}

$c = counter_gen();
say x $c->();		# (1)実行すると1 と表示
say x $c->();		# (2)実行すると2 と表示
say $c->() x 2;		# (3)実行すると33 と表示
$c->() x 2;		# (4)
say $c->();		# (?) - さあ、ここでは何が表示されるでしょう??

答え

(3)は$c->() の評価結果である3 が、繰り返し演算子x によって'33' となるのはご存知でしょうが、

(4) の部分では、なんと$c->() の評価が繰り返される動きになるようです??

結果、(?) の部分は 5 ではなく 6 ということになります。

うーむ、これは知らなかった。

…とおもったらあらら!!(後日記)

ハテブにいただいていたコメントに、色々指摘をいただいておりました。

  • hirafooさん…use strict; しないコードの動き。つか$cが
  • fbisさん…何か色々おかしい気が。Deparseした結果が見たい。
  • kitsさん…試したところ最後の結果は5だった。/ 、say x $c->() は use warnings; では警告が出る。

あわててコードを見ると、どうも書き換え途中の動かないコードを上げていたようです。これはひどい。。。

その上、use strict; use warnings; もつけ忘れていますね。

大変申し訳ない!

気を取り直して、改めて書き直したものは以下のとおり。

#!/usr/bin/env perl
use strict;
use warnings;

sub counter_gen{
        my $c = 1;
        return sub { return $c++; }
}

my $cg = counter_gen();
print $cg->() . "\n";      # (1)実行すると1 と表示
print $cg->() . "\n";      # (2)実行すると2 と表示
print $cg->() x 2 . "\n";  # (3)実行すると33 と表示
$cg->() x 2;               # (4)
print $cg->() . "\n";      # (?) - さあ、ここでは何が表示されるでしょう??

そして、実行結果は...

Useless use of repeat (x) in void context at test.pl line 14.
1
2
33
5

肝心の(?) の部分は、最初に私が書いた結果とは異なり、6ではなく5 になっています。

そして(4) のところでは警告になっていますね。

なるほど、ここまで来てやっと腑に落ちました。

わざわざ指摘をくださったみなさん、ありがとうございました!

tyrutyru 2010/05/17 23:15 こんにちは。

perl5.10だとそのままだとエラーが出るので先頭に

use v5.10;

と入れて試したら

33
5

と出たのでバージョン固有のperlのバグでは?

harupiyoharupiyo 2010/05/31 20:56 tyru さんこんにちは。
どうもこうも…私がひどいコードを書いていただけのようです。
かたじけない!!
フォローありがとうございました!

2010-05-14 [windows] タイル型ウィンドウマネージャ続報

タイル型ウィンドウマネージャ続報  タイル型ウィンドウマネージャ続報を含むブックマーク

タイル型ウィンドウマネージャという古くて新しい風 の続報として、しばらく使ってみた結果の報告です。

HashTWM ⇒ dwm-win32

最初に選んだHashTWM はポップアップウインドウにあるボタンが上手くクリックできないなど、致命的な問題があることがわかりました。

そこで、最初は敬遠したdwm-win32 使ってみるとウィンドウ切り替え速度も実に軽快でいい感じ!

…ところが、使っているうちに落ちたりして、安定感はいま一歩。

(配布のものはalpha1,2 とあるから、そもそもまだ安定版ではなかったのかな。)

結論

Windows のタイル型ウィンドウマネージャーはまだ不遇な感じだなと思いました。

(Ubuntuxmonad を使って幸せになっている今日このごろ。キーアサインも前回紹介したHashTWM のものと基本はいっしょです。)