Unyablog.

のにれんのブログ

SQLクエリチューニングメモ

  • table: "table_name"
A B
"a" 1
"a" 2
"a" 4
"b" 1
"b" 4
"c" 1
"c" 3

のようなデータが 100k レコードほど存在するデータベースにおいて、指定のB (b_list) が存在するAランダムに一つ抽出 する。

例:

  • blist: [1] -> mathced A: ["a", "b", "c"] -> ランダムに取り出し -> "b"
  • blist: [1, 2] -> mathced A: ["a"] -> ランダムに取り出し -> "a"
  • blist: [1, 4] -> matched A: ["a", "b"] -> ランダムに取り出し -> "b"

このとき、

select A from table_name
    where B in ({ b_list })
    group by A
    having count(distinct B) > { b_list_length - 1 }
    order by random()
    limit 1
;

としていたが、1.5 秒ほどかかって困っていた。

order by random() があまり良くなく、 count して自前でランダムしたほうが良いという話を見る *1 が、そもそも limit 1 を消し、得られた結果を count しても同程度に遅いのであんまり関係無さそう。

count(distinct B) が悪いのではということで、はじめから B でも group by して count() はグループ化された A の個数を数えるだけにした。

そして、

select A from (
    select A from table_name
        where B in ({b_list})
        group by A, B
    )
    group by A
    having count() > { b_list_length - 1 }
    order by random()
    limit 1
;

とすると 0.8 秒ほどになり、そこから A,B 間に index を貼ることで 0.6 秒ほどになった。

蛇足

その後 group by は暗黙のソートがあるので exists を使おう!という数年前の記事を見かけた。

実際にやってみたら 0.8秒と遅くなってしまったので、 group by に戻した。

参考になったサイト

Use Subqueries to Count Distinct 50X Faster

norifyDataSetChanged でアニメーションする in RecyclerView

stackoverflow.com

  • RecyclerView.Adapter#getItemId()ユニークな ID を返す
  • RecyclerView.Adapter#setHasStableIds(true) を行う

これだけで RecyclerView.Adapter#notifyDataSetChanged() のみでもいい感じにアニメーションしてくれます。

パフォーマンスも良くなります。

ttps://www.reddit.com/r/androiddev/comments/2lr8bf/what_does_recyclerview_sethasstableids_do_and_why/*1

StackOverflow では supportsPredictiveItemAnimations()true を返すようにする必要があると書いてありますが、 Support Library 23.4.0 時点の LinearLayoutManager では必要ありませんでした。

実演

getItemId()ユニークなID(今回はデータの primary key) を返し、全て notifyDataSetChanged() で変更を伝えています。

毎回 notifyDataInserted() 等を呼ぶよりも簡単にできて便利。

*1:reddit リンク入れると投稿失敗するみたいなので h 抜いています

Haskell入門 14日目

十四日目

VBoxHeadlessTray を入れてみた。これだと一々 VM 起動してること気にしなくてよさそう。

SICP 読まないとなあとか思ってるこの頃。

Haskell, monad ぐらいまでやろうかなあとか思って目次見たけど一番最後だった。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

第8章

入出力。結構難しいとか聞いたことある。

8.1

  • いい話

8.2

  • ついに ghci 以外から呼び出すようになるのか
  • コンパイルだ。。。!
    • まあ ghci からロードしてる時も呼び出してるのだけど
  • 返り値はあってアクション
  • C みたいに main がデフォで行われるみたいな感じかな

8.3

  • 急に命令形っぽくなってきた
    • main 自体がIOアクションを返す
  • getLine はIOアクションで、String を返す
    • printStrLn はIOアクション自体で、<- はそこから取ってくるみたいな感じ仮名
      • 見た感じリスト内包のアレとは違いそう。
  • do 構文自体はIOアクションを返すんかな
  • do の中で = 使ったら怒られたけどそういうもんなのか
    • let 使ったらできた。
  • haskell, 地味にインデント必要なのが難しいと思う*1
foo <-  putStrLn "hello"
putStrLn $ show $ foo == ()

としたら True と出てなるほどって感じ。

  • ghci でやっても do 内でやれって怒られた。

    • もしやと思って let 付けたら通った。
  • null 初めて見た気がする

    • Foldable を引数に取るので isEmpty みたいなもんっぽい
  • return もIOアクションなのかー

    • do 節で終わりに何もしない時とかに使う

8.4

  • それっぽい入出力群
  • 入力を反転して返すの、when 使えば
when (not $ null line) do putStrLn $ reverse line

に省略できて便利

  • forMmapM はIOアクションの結果を入れてくれる

感想

  • 一気に実用的になった感じで楽しかった。
  • なるほどいろいろ考えられてるなぁという感じ
  • これがよく聞くIOモナドかと思いながら読んでた。

*1:まあpythonもそうだけど

Haskell入門 13日目

十三日目

時間が開いてしまってやることを忘れたのでまずここのログを読みなおした。メモ残すこと大事だなって思いました()

WindowsHaskell しようかと思って Stack いれたけど cmd 使うこと考えると嫌になってすぐアンインストールしました*1

7.9

  • 型クラス懐かしい
    • 要するにjavaインターフェースみたいなもんでしょっていうjava変換おじさんになってる。
  • 自動でやってくれるけど今回はちゃんとやってみますねっていう感じか
    • Serializable 的な hogehoge
  • 循環的な定義もできるの良い

  • 試しに Show を付けなかったらghci で Red だけするとエラーになった。これ前もやったかもしれない。

  • サブクラスは制約っぽい

  • Maybe は直接できないので二重にやるなるほど

  • このへん Haskell 勝手にやってくれるの良いですね。

7.10

  • if の中になんでも入れれるの便利で java 使ってると羨ましくなる。
型クラス制約付きの引数を具体型によってパターンマッチングはできるのか?
hoge :: (Num a) => a -> String

といった関数がある時、Int とそれ以外で挙動を変えたい場合はどうすればいいのか?と思って調べたメモ。

データ型の直和型や列挙型をパターンマッチングするのは簡単にできるのですが...

試しに

hoge :: (Num a) => a -> String
hoge (x::Int) = "aaa"
hoge x = "hoge"

などと書くと Perhaps you intended to use ScopedTypeVariables と言われたのでそうしてみたけど関係なさそう。

しばらく考えたらこういう案件こそ型クラスを使うべきなんだなあと気付きました。

  • 最悪っぽいの

http://stackoverflow.com/questions/4131552/haskell-check-if-integer-or-check-type-of-variable

にある二番目の解答。

import Data.Typeable
isInteger :: (Typeable a) => a -> Bool
isInteger n = typeOf n == typeOf 1

最悪っぽい。

  • yesnoIf が簡単に実装できるのは便利だなあという感じ。

7.10

  • instance Functor [] where と書くことになるのは、class Functor
class Functor f where
   fmap :: (a -> b) -> f a -> f b

と宣言されていて、これによって f 自体は 具体型ではなく型コンストラクタになる ためである。

そのため、

class NonyFunctor f where
    fmap :: (a -> b) -> f a -> f b

instance Functor Int where

として具体型を入れると

The first argument of ‘Functor’ should have kind ‘* -> *’,
  but ‘Int’ has kind ‘*’
In the instance declaration for ‘Functor Int’

と怒られることになる。

  • fmapmap が同じなの、なるほどという感じ

  • 要するに、fmap は型クラスの中にある値に直接関数をどうこうしたいときに使うものみたいな感じですね

  • Either a は型コンストラクタ

    • こういうのを見ると左にエラー入れるってのもなるほど感ある
    • Either いみわからんとか言ってたけど tuple とはまた別の物ですね。片方しか入れられないし。

7.11

  • :k 便利

:k Num とすると Num :: * -> GHC.Prim.Constraint となった。

これは型クラス制約のことで、 Num a は型クラス制約となることの現れ。

:k FunctorFunctor :: (* -> *) -> GHC.Prim.Constraint となり、型コンストラクタを引数に取り型クラス制約になるということ。

感想

  • またまた久しぶりになってしまった...
  • 型クラス制約と型コンストラクタがごちゃごちゃになってたので 7.11 読んでよかった。
    • 段々難しくなってきた気もするけどしばらくブランク空いたからかもしれない

*1:今は Arch LinuxVM でやってます

Android Studioでのビルドをクラウドで行い開発を高速化する

こんにちは。学校も始まり最近は健康な時間に起きています*1

今回は 手元の Android Studio からビルドのみをクラウドで行う ことによって快適な生活を手に入れる話です。

概要

  • ビルドを移譲できる Android Sutudio のプラグインを書きました
  • これを使ってクラウドのリッチなマシンでビルドを行い高速化
  • ビルドのみが移譲されるので操作感は変わらない
  • 実装は割りと無理矢理

*1:ちなみに現在風邪を引いて寝込んでいます

続きを読む

Raspberry pi に GitWeb を入れた

昔 Raspberry Pi に GitLab を入れた記事を書きました。

nonylene.hatenablog.jp

この時、重い重い言いながら運用していました*1が、ニヶ月ほど前にSDカードが壊れる事件が起きて、再構築した時に入れるのがめんどくさくて*2入れてませんでした。そもそもSDカードが壊れたのが GitLab をアップデートして reconfigure 中に突然再起動した後だったのでちょっと怖いというのもあります((

しかし4月になり実験用のレポジトリを作る必要が出てきたため、今回は GitLab をやめて GitWeb を使うことにしました。

*1:Slack に投稿できたりして便利

*2:まあ Ansible コマンド打つだけなんですけど...

続きを読む

クラウドの Linux 上で Android Studio をリモート操作するネタ

※実用性はほぼありません。

Andorid のビルドが最近遅くて、ブラウザで動画流しながら StackOverflow 調べながら twitter 流しながら…とやっているとすぐに mac がファンファンなりだして音声は途切れるわ熱くなるわという状態になります😭

メモリ 8GB だし、数年前の mac だから仕方ないといえばそうなのですが新しい mac を買うのはまだ早い気もする。

結局いい感じの IaaS を借りてそこでビルドすると早いのではという結論にたどり着き、ここ三週間ほどいろいろ試行錯誤してる中で出てきた一つのネタです。

本題

Android Studioクラウドで動かしてリモート操作しよう

ビルドだけ Linux 側でやるのはコマンド打てばいい話なのですが、そうするとせっかくの IDE の機能を活かすことができません。どうやら ADB の remote port forward はできる*1という話を見たので、それなら向こう側で Android Studio ごと動かしちゃえばいいじゃんと考えました。

続きを読む