Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2018早稲田大学アルゴリズムとデータ構造特別講義 / 2018-Algorithm-And-Data-Structure-Course-At-Waseda

2018早稲田大学アルゴリズムとデータ構造特別講義 / 2018-Algorithm-And-Data-Structure-Course-At-Waseda

82f797c1864841a4aca94079b8508004?s=128

Yoshiyuki Asaba

December 21, 2018
Tweet

Transcript

  1. Webサービスとアルゴリズムとデータ構造 freee株式会社

  2. 2015年5o月にfreee株式会社へ入社 執行役員 プロダクト基盤(SREなど)本部長 RDBMSと運用自動化が大好き 学生時代 形式仕様言語の研究とACM/ICPC 社会人 SRA→Microsoft→グリー→スタートアップ2社→freee Yoshiyuki Asaba

    浅羽 義之 freee株式会社 2
  3. 3     アイデアやパッションやスキルがあればだれでも、 ビジネスを強くスマートに育てられるプラットフォームをつくる スモールビジネスを、世界の主役に。

  4. 4 創業からIPOまで、中小企業活性化のためのサービスを一気通貫で提供 freee会社概要 ❂ 納税する ↗ 育てる ↻ 運営する ✩

    はじめる 会社設立 freee 開業 freee クラウド会計ソフト freee 人事労務 freee (マイナンバー管理 freee 含む) クラウド申告 freee 161億603万円 (資本準備金等含む) 従業員数 事業内容 クラウド型バックオフィスサービスの開発・販売 資本金 設立年月日 2012年7月 465名(2018年6月末時点) 2017年「働きがいのある会社」 ランキング3位
  5. 5 100万 サービス開始5年で 1,000,000 事業所数累計 事業所突破 No.1 シェア* ※出典:BCN クラウド会計ソフト市場調査。n=418、webアンケート調査

  6. 01 Webサービスの裏側 なぜアルゴリズムとデータ構造が必要なのか 6 Section

  7. 7 Webサービス(1) インターネット上で何かしらの価値を提供するシステム • クラウドや*aaSなどと表現することもある ◦ SaaS, PaaS, IaaSなど •

    freeeはビジネス向けのサービスを提供 ◦ B2B (Business To Business) ◦ ブラウザだけでなくiOSやAndroidのアプリからサービスを使うケースも含める
  8. 8 Webサービス(2) リクエスト • ブラウザやアプリからWebサービスに対して、何らかの処 理を依頼すること レスポンス • リクエストに対するWebサービスからの応答 •

    レスポンスの内容に応じてブラウザやアプリが画面を書き 換える
  9. 9 Webサービスの一般的な要件 基本的にはいつでも使える • サービスが落ちていると嫌ですよね 可能な限り速く結果を返す • レスポンスが速いほうがサクサクサービスを使えて良いですよね • できればミリ秒単位で結果を返したい

    ◦ 1秒 = 1,000ミリ秒 ユーザーを識別する • ログインすることによって、自分専用のサービス提供をしてほしいですよね
  10. 10 サービスが常時稼働しているとは? 前提:マシンは壊れるもの • CPU, メモリ, ストレージ, その他パーツなど • ソフトウェアのバグによって機能しなくなることもある

    ◦ 物理的に壊れなくても、OS, ミドルウェア, アプリケーションが壊れることによって事実上 の壊れた状態になることも 壊れても大丈夫なように複数のマシンでサービスを動かす • 「冗長化」と呼んだりします ハードウェア(PC, tablet, smartphone等) OS(iOS, MacOS, Windows, Linux等) ミドルウェア アプリケーション
  11. 11 レスポンスを速く返すとは? 計算を速く終わらせる • ハードウェアのスペックをあげる • ソフトウェアを効率よく動かす ◦ アルゴリズムとデータ構造が特に重要 •

    不要な計算を後回しにする サーバーの忙しさを下げる • 少ない計算量でも、同じ処理が一台でたくさん動いている と待たされる ◦ リクエストを複数のサーバーに振り分ける ◦ 負荷分散と呼ぶ 待ち行列 • リクエストを即座に処理し始める(待たせない)
  12. 12 冗長化と負荷分散 複数台でリクエストを受け付ける • どれかが故障してもサービスを継続できる • 受け付けるだけで、処理は別で行う(転送する) リクエストを処理するサーバーも複数用意 • Webサーバー、アプリケーションサーバーと呼ぶ

    • 一台で処理できる数は限界がある • 複数台あれば限界が理論上はN倍増える ◦ ただしお金がかかる
  13. 13 データを保存する Webサービスは大抵は何かのデータを保存します • 会計データ • 画像 • SNSの投稿 •

    チャットメッセージ 保存するためのシステムがあります • RDBMS, KVS, ... • あとで説明予定 これ
  14. 14 負荷分散とデータの整合性 状態(データ)を持つサーバーの処理を負荷分散させるの は難しい • 状態を複数のサーバーで同じにしないといけない • 負荷分散させるためにはある種の諦めが必要と言われている ◦ CAP定理

    Webサーバーは状態を持たないのが普通 • →増やしやすい 詳細は分散システムの授業で 説明があると思います
  15. 15 つまりレスポンスを速くするとは すべての場所で処理を速く終わらせる • ロードバランサー • Webサーバー • 大量のデータの読み書き トータルで速くする!

  16. 16 すべてを紹介するのは難しいので RDBMS (Relational DataBase Management System) • データの検索 •

    データの並び替え • データの結合 KVS (Key Value Store) キューシステム
  17. 02 RDBMS概要 17 Section

  18. 18 RDBMS Relational DataBase Management System • 簡単に言うと ◦ 安全にかつ高速に、大量のデータを保存・検索できるシステム

    ◦ WebサービスだとMySQLやPostgreSQLがよく使われている ◦ RDBMSは大抵のサービスで使われていると思って良い データベースの授業は3年で開講されるそうですが、 その場合は絶対に受けておいたほうが良いです!!
  19. 19 RDBMSのイメージ スプレッドシートみたいなもの • テーブル • 行 • 列 特徴

    • 検索ができる • 大量データを扱える • 同時操作が可能 • その他にもいろいろありますが、来年の講義でぜひ学んでください
  20. 20 SQL Structured Query Language • RDBMSに命令をするための言語 • 宣言的に欲しいデータの検索条件を記述 •

    データの挿入、更新、削除も可能 • どのように検索するかはRDBMSが裏で決める SELECT 学籍番号, 名前 FROM 学生 WHERE 都道府県 = ‘東京都’ 命令:学生というテーブルの中から東京都の学生だけを学籍番号と名前を抽出したい
  21. 21 RDBMSの実装 各製品によって挙動は異なります • SQLは仕様がある • それをどう実装するかは実装者次第 あくまでも概念として紹介します • 興味ある人はマニュアル

    or OSSのRDBMSのコードを読んでみてください
  22. 03 RDBMS上での検索 22 Section

  23. 23 データの検索 線形探索 • データをすべて検索する ◦ 配列を最初から最後までスキャンするイメージ • ストレージの速度が速くなったとはいえ遅い •

    フルスキャンと呼んだりします インデックス探索 • 次のページから説明します • 二分木探索をイメージしてもらえると
  24. 24 例:教科書から特定の内容が書かれているページに飛びた い 「クイックソート」というキーワードを探す • その本が1,000ページあるとする 探し方 • 巻末にある「索引」から「クイックソート」という単語があるか調べて、あればそのページに 移動する

    ◦ インデックススキャン • 本を1ページ目から探していく ◦ 1,000ページを読み込まないといけないので時間がかかる ◦ 「変数」という一般的な用語だといろいろなページに出てくるので、先頭から全部確認し たほうが速い ▪ ↑は選択率が高い状態 ▪ 意味があるかどうかは置いておいて
  25. 25 B+Tree 木構造の一つ • インデックス(索引)を表現するデータ構造の一つ • ソート済みのデータを保持する • メモリ上で収まりきらないようなデータを効率よく扱えるように工夫されている ◦

    前提:ストレージのオペレーションは遅い インデックス探索 • 次のページから説明します • 二分木探索をイメージしてもらえると By Grundprinzip - Own work, CC BY 3.0, https://commons.wikimedia.org/w/index.php?curid=10758840
  26. 26 B+Treeの特徴 実際のデータは葉にしか持たない • B-Treeは節にも持つ • ブロックデバイスに適している ◦ ブロックデバイスとは簡単に言うと外部ストレージ(HDD, SSD等)

    ◦ 一回のストレージのオペレーションをブロックという塊で操作する • 節を1ブロックに大量に詰め込むことができるので、木の高さが低くなる
  27. 27 B+Treeの特徴 根から葉への高さは均等 • B-Treeは節にも持つ • 大量のデータから一つ取り出したいときに、数ブロックスキャンすれば到達できる 隣のブロックへの参照を持っているので、範囲検索も高速

  28. 28 B+Treeの挙動を知りたい場合 小さいCのコードがあります • http://www.amittai.com/prose/bplustree.html $ gcc -g -O0 btp.c

    $ ./a.out ... Enter any of the following commands after the prompt > : i <k> -- Insert <k> (an integer) as both key and value). f <k> -- Find the value under key <k>. p <k> -- Print the path from the root to key k and its associated value. r <k1> <k2> -- Print the keys and values found in the range [<k1>, <k2> d <k> -- Delete key <k> and its associated value. x -- Destroy the whole tree. Start again with an empty tree of the same order. t -- Print the B+ tree. l -- Print the keys of the leaves (bottom row of the tree). v -- Toggle output of pointer addresses ("verbose") in tree and leaves. q -- Quit. (Or use Ctl-D.) ? -- Print this help message. > i 3 3 |
  29. 29 ソースコードを追いかけるTips デバッガを使うとコードを追いやすいです • gdb

  30. 04 RDBMSのソート 30 Section

  31. 31 巨大なデータのソート ソート例 • 学生さんのリストをテストの成績順にソートしたい メモリに収まる範囲であればクイックソートでソートする • 数百行とかであれば余裕でメモリ上でソートできる • オンメモリで平均的に速いソートアルゴリズム

    メモリに収まりきらない場合はファイルを使ったソート • マージソート • ファイルを使うので遅い •
  32. 32 Top-N sort (Top-k selection) 並び替えた結果から上位10件を取りたい • SELECT * FROM

    students ORDER BY score DESC LIMIT 10 • 該当する行をすべてとってきてソートするのではなく、上位N件だけを保持してソートする
  33. 33 B+Treeの特性を活かしたソート B+Treeは順番を保持したデータ構造 • その特性を活かすことも可能(検索条件次第)

  34. 05 RDBMSのテーブル結合 34 Section

  35. 35 テーブル結合とは 2つのテーブルを指定した条件で別のテーブルを作る(結合, JOIN) • 例:数字が一致する行を結合したい 学籍番号 都道府県 コード 4

    101 2 102 1 102 7 104 都道府県 コード 都道府県名 101 東京都 102 神奈川県 103 長野県 104 愛媛県 駆動表 内部表 結合 学籍 番号 都道府県 コード 都道府県 コード 都道府県名 4 101 101 東京都 2 102 102 神奈川県 1 102 102 神奈川県 7 104 104 愛媛県
  36. 36 結合例1 特定の学生がどこ出身か? • 都道府県コードをキーにテーブルを結合 • →学籍番号と都道府県名を取得可能になる 学籍番号 都道府県 コード

    4 101 2 102 1 102 7 104 都道府県 コード 都道府県名 101 東京都 102 神奈川県 103 長野県 104 愛媛県 学生テーブル (駆動表) 都道府県テーブル (内部表) 都道府県コードの一 致を条件に結合 学籍 番号 都道府県 コード 都道府県 コード 都道府県名 4 101 101 東京都 2 102 102 神奈川県 1 102 102 神奈川県 7 104 104 愛媛県
  37. 37 結合例2 特定の学生がどの講義を履修したか? • 学籍番号をキーにテーブルを結合 • →学籍番号と講義IDを取得可能になる • →さらに講義名を取得したい場合は講義テーブルを結合 学生テーブル

    学籍番号 名前 4 山田 2 田中 1 鈴木 7 木村 学籍番号 講義番号 1 1001 1 2001 4 3001 2 1022 7 4000 2 1001 講義番号 講義名 1001 英語 1022 会計学 3001 ネットワーク 2001 論理学 4000 線形代数 履修テーブル 講義テーブル
  38. 38 テーブル結合(JOIN)をどう実現するか 代表的なものは3つのアルゴリズム • Nested Loop Join • Merge Join

    • Hash Join すでに習ったアルゴリズムを組み合わせています のちほど3つのアルゴリズムを実装していただきます
  39. 39 サンプルデータ 1次元の整数の配列を2つ用意 • 整数は学籍番号や講義番号だと思ってください • 結合結果の順番は不定 4 山田 9

    高橋 2 田中 1 鈴木 7 木村 2 1022 10 2001 5 1001 7 1003 2 5000 2 田中 2 1022 2 田中 2 5000 7 木村 7 1003 結合 学生テーブル 履修テーブル
  40. 40 Nested Loop Join 単純な2重ループのアルゴリズム • 全組み合わせを比較し、条件にあったものを返す • もう少し丁寧に書くと ◦

    駆動表の条件にマッチするのを内部表から持ってくる、というのを繰り返す ◦ B+Treeでは条件次第では内部表から早くデータを取ってこれる 4 9 2 1 7 2 10 5 7 2
  41. 41 Merge Join • ソートをあらかじめ両方やってからマージしていく • 言葉で説明するのは難しいので擬似コードを書く 4 9 2

    1 7 2 10 5 7 2
  42. 42 擬似コード (PostgreSQLソースコードのコメントより引用) Join { get initial outer and inner

    tuples INITIALIZE do forever { while (outer != inner) { SKIP_TEST if (outer < inner) advance outer SKIPOUTER_ADVANCE else advance inner SKIPINNER_ADVANCE } mark inner position SKIP_TEST do forever { while (outer == inner) { join tuples JOINTUPLES advance inner position NEXTINNER } advance outer position NEXTOUTER if (outer == mark) TESTOUTER restore inner position to mark TESTOUTER else break // return to top of outer loop } } }
  43. 43 両方のデータをソートしてからスタート • 現在の場所を両方のテーブルにマークする • 1 < 2なので左をずらす 1 2

    4 7 9 2 2 5 7 10
  44. 44 • 2 == 2 ◦ どこから一致したかをマークする • 結果:{2,2} 1

    2 4 7 9 2 2 5 7 10
  45. 45 • 2 == 2 ◦ さらに進める • 結果:{2,2}, {2,2}

    1 2 4 7 9 2 2 5 7 10
  46. 46 • 2 < 5 ◦ 左のテーブルを先に進める ◦ 右のテーブルのマークを戻す •

    結果:{2,2}, {2,2} 1 2 4 7 9 2 2 5 7 10
  47. 47 • 4 > 2 ◦ 右のテーブルを先に進める • 結果:{2,2}, {2,2}

    1 2 4 7 9 2 2 5 7 10
  48. 48 • 4 > 2 ◦ 右のテーブルを先に進める • 結果:{2,2}, {2,2}

    1 2 4 7 9 2 2 5 7 10
  49. 49 • 4 < 5 ◦ 左のテーブルを先に進める • 結果:{2,2}, {2,2}

    1 2 4 7 9 2 2 5 7 10
  50. 50 • 7 > 5 ◦ 右のテーブルを先に進める • 結果:{2,2}, {2,2}

    1 2 4 7 9 2 2 5 7 10
  51. 51 • 7 == 7 ◦ どこから一致したかをマークする ◦ 右のテーブルを先に進める •

    結果:{2,2}, {2,2}, {7,7} 1 2 4 7 9 2 2 5 7 10
  52. 52 • 7 < 10 ◦ 右のテーブルのマークを戻す ◦ 左のテーブルを進める •

    結果:{2,2}, {2,2}, {7,7} 1 2 4 7 9 2 2 5 7 10
  53. 53 • 9 > 7 ◦ 右のテーブルを進める • 結果:{2,2}, {2,2},

    {7,7} 1 2 4 7 9 2 2 5 7 10
  54. 54 • 9 < 10 ◦ 右のテーブルを進めたいがこれ以上無いので終了 • 結果:{2,2}, {2,2},

    {7,7} 1 2 4 7 9 2 2 5 7 10
  55. 55 擬似コード (再掲) Join { get initial outer and inner

    tuples INITIALIZE do forever { while (outer != inner) { SKIP_TEST if (outer < inner) advance outer SKIPOUTER_ADVANCE else advance inner SKIPINNER_ADVANCE } mark inner position SKIP_TEST do forever { while (outer == inner) { join tuples JOINTUPLES advance inner position NEXTINNER } advance outer position NEXTOUTER if (outer == mark) TESTOUTER restore inner position to mark TESTOUTER else break // return to top of outer loop } } }
  56. 56 Hash Join 条件となる値をキーにしてハッシュテーブルを作る • どちらか小さいテーブル • ハッシュテーブルの特性上、JOINの条件が範囲条件の場合は使えない 4 9

    2 1 7 2 10 5 7 2
  57. 57 練習問題 以下のJOINアルゴリズムを実装してください • Nested Loop Join • Merge Join

    ◦ ソートは何で実装しても良いです • Hash Join ◦ ハッシュテーブルは何を実装しても良いです それぞれのJOINアルゴリズムについてどういう特性があるか考えてみてくだ さい
  58. 58 練習問題 入力 • 配列の長さNとそれに続くデータを駆動表・内部表で用意 ◦ 3種類を用意 • ランダムに10万件の数字を生成するスクリプトも作ってみてください ◦

    余裕があれば 3 // 駆動表のサイズ 2 1 3 4 // 内部表のサイズ 3 2 3 1
  59. 59 練習問題 出力 • マッチした値と件数 ◦ 重複分も含める ◦ マッチした値の順番は問いません ◦

    件数がそれぞれのJOINで同じことを確認する 1 1 2 2 3 3 3 3 join count = 4
  60. 60 サンプル解答 https://github.com/y-asaba/RDBMS-join-exercise

  61. 06 KVS(Key Value Store) 61 Section

  62. 62 KVS KVSは色々なミドルウェアがある • Keyとそれに対するValueを保持する ◦ Keyでデータを検索 • 代表的なものは連想配列をハッシュテーブルを使って実装 key-valueをオンメモリで持っておく実装が多いシステム

    • データを永続化できるものもある • キャッシュ用途に使われることが多い • memoryが溢れそうな場合はLRU(Least Recently Used)等のポリシーで消すこともある
  63. 63 KVSが向かないケース 集計や結合などのデータに対して複雑な操作が必要な場合はRDBMS キーの範囲検索 • 製品(LevelDB等)によってはできるので、全てではない

  64. 64 KVSの使用例 sessionデータを一時的に保存し、リクエストごとに参照 • sessionとはサービスにログインされると作られるデータ • ハッシュテーブルはO(1) • B+TreeはO(log_b N)

    ◦ bはどれくらい説に詰め込めるか(2分木の場合は2) ◦ 外部ストレージへのI/Oも発生する可能性がある web server web server session key value Athoh4Phu0aeng9wureJ Aさんの識別子 fohphaChahmoo1saizuu Bさんの識別子 Aeng6ei1phei0LohQu8i Cさんの識別子 GET (sessionの有効性の確認) SET (login時) ハッシュテーブル (session keyは実際はもっと長い)
  65. 07 キューの応用例 65 Section

  66. 66 キューの前に Webサーバーは基本的に早く応答を返したい • 重い処理を後回しにしたい リクエストの同期処理と非同期処理 • 同期処理とはユーザーへ応答を返すときには処理が終わっている処理 • 非同期処理とはユーザーへ応答を返すのとは別に裏で行われる処理

    ◦ 別の形でユーザーへ通知するか、そもそも通知が不要なものもある
  67. 67 処理を後回しにしたい例 使い方例 • Webサーバーがリクエストを受け付けて、裏で重い処理をする • ログをキューに投げて、裏でデータ分析用の基盤に投げる • メール送信等の多少遅れても問題ない処理をする

  68. 68 キューの応用例 キューを管理するミドルウェアもしくはサービスがある • リクエストを受けたサーバーがメッセージをキューに入れる • 誰かがキューからメッセージを拾ったら、他の人は拾わない(アトミックな処理) web server web

    server Queue Service push Job Worker Job Worker pull
  69. 69 mkfifoコマンドを使った簡単な実験 コンソールを2つ立ち上げてください(Windowsだと動かないかも) • mkfifoを通してメッセージを送って処理をします • 整数を送って、2倍した値を出力する % mkfifo waseda

    % tail -f waseda | awk '{print $1*2}' 200 2 4 6 8 10 % echo 200 > waseda % seq 5 > waseda キューを待ち受ける キューにデータを入れる
  70. 08 まとめ 70 Section

  71. 71 アルゴリズムとデータ構造を知っておくと良いこと データ構造とアルゴリズムはいろいろなところで使われている • それぞれ特性があるので、状況に応じて使い分けることが大事 ◦ 外部記憶領域に書き出す可能性があるからクイックソートではなくマージソートを使う ◦ Merge Joinは結合の条件比較の数は少ないが、そのかわり先にソートする必要がある、等

    • レスポンスタイムが遅くなったときに裏でどういうアルゴリズムが動いているかを知っているかで 解決できることが増える つまり、サービス開発には欠かせない知識!!
  72. スモールビジネスを、 世界の主役に。