Pro Yearly is on sale from $80 to $50! »

Webサービスにおける外 部API使用とMySQL位置情報機能 #TechLunch

Webサービスにおける外 部API使用とMySQL位置情報機能 #TechLunch

t(水) @ Livesense TechLunch
発表者:島田 喜裕

E60aa4f80303f3f386898546ddb3686a?s=128

Livesense Inc.

April 23, 2014
Tweet

Transcript

  1. Webサービスにおける外 部APIの使用とMySQLの 位置情報機能 yoshihiro shimada

  2. はじめに • キャッシュ • MySQLによる位置情報の検索

  3. 外部APIの活用 有名なサービスは何らかのAPIを提供 ↓ ここ最近のほとんどのWebサービスが何らかの形 で外部APIを使用している ↓ 情報・ライブラリが豊富に揃ってきている ↓ 書籍やWebサイトではあまり触れられない問題もあ る

  4. rate limits • rate limitsとは?  APIによってはリクエストの数に制限がある。  その制限を超えるとAPIが一時的に使用不可 となる。 (頻繁にlimitを超えると)以後のアクセスが拒否 されるなど、サービス継続に致命的な事態も

    ・・・。 • 対策 APIのレスポンをキャッシュ。 →API呼び出し回数、レスポンスタイムの低減
  5. キャッシュの設計 ▪ 保存場所、実装方式の選択 ▪ キャッシュのキーと内容

  6. 例)位置情報APIを使用したWebサービス • スマートフォン→現在地周辺のお店検索 • Web→エリアとキーワードによるお店検索 位置情報APIへのリクエスト スマートフォン 現在地情報(緯度、経度) Web エリア情報とキーワード

  7. $key = "$lat:$lng:$keyword"; //キャッシュの読み出し if (($result = getMyCache($key)) === false)

    { //キャッシュなしの場合・・・ //APIを呼び出して $result = callAPI($lat, $lng, $keyword); //結果をキャッシュに保存 saveCache($key, $result); } return $result; コード例 この方法だとスマートフォンの場合に上手く動作し ない
  8. 設計のまとめ 1. キャッシュのキーは緯度、経度 2. 緯度、経度から近くのデータがキャッシュにあれ ば、そのデータを使用 3. キャッシュするデータはAPIのレスポンをそのま ま保存

  9. MySQLにおける空間情報の機能 MySQLは、位置情報を扱うための仕組みがある • 位置情報を保存するデータ型 • 位置情報を扱う関数 • 位置情報の検索を効率的にするインデックス 位置情報とは位置(点)でなく、直線・ポリゴン及び それらが複数集まったデータ

    →Spatialデータ型
  10. ▪ 基本データ型 ▪ 関数 1. Spatialデータ型の値を作成する関数 2. Spatialデータ型の各種プロパティを取得する 3. 2つのSpatialデータの関係を調べる関数

    POINT型 点を表現 LINESTRING型 線を表現 POLYGON型 平面を表現 GEOMETRY型 上記のどれでも入れられる
  11. Spatialインデックス 位置情報の検索を効率的に行うインデックス。 Spatialデータ型にはb-treeインデックスを貼っても 使われない。 現状ではSpatialインデックスが使用できるのは MyISAMのみ。

  12. CREATE TABLE IF NOT EXISTS `cache_fs_search` ( `cache_id` int(11) NOT

    NULL AUTO_INCREMENT, `latlng` point NOT NULL, `result` mediumtext NOT NULL, PRIMARY KEY (`cache_id`), KEY `keyword` (`keyword`), SPATIAL KEY `latlng` (`latlng`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; • テーブル定義 • ユーザ定義関数 DELIMITER $$ DROP FUNCTION IF EXISTS `dbname`.`distance_in_meter` $$ CREATE FUNCTION `distance_in_meter`(a POINT, b POINT) RETURNS double DETERMINISTIC COMMENT 'distance function' BEGIN RETURN round(glength(linestring(a, b)) * 111000); END $$ DELIMITER ;
  13. a b glength(linestring(a, b)) 円周約40,000km

  14. INSERT INTO cache_fs_search (latlng, result) VALUES (GeomFromText('POINT(35.00000 139.0000)'), 'test result')

    .... • データ • 位置情報の検索 SELECT cache_id, x(latlng) as lat, y(latlng) as lng, result, distance_in_meter(latlng, PointFromText('POINT (35.691147 139.702084)')) d FROM `cache_fs_search` WHERE distance_in_meter(latlng, PointFromText('POINT (35.691147 139.702084)')) < 100 この方法だとインデックスが使用されない
  15. Spatialインデックスが使われる検索 • 検索したい位置を中心に直径200mのバウン ディングボックス内の結果を、MBRWithin関数を 使用して取得 • 得られた結果のうち距離が100m以内のものを フィルターして使用 200m 100m

  16. SELECT cache_id, x(latlng) as lat, y(latlng) as lng, result, distance_in_meter(latlng,

    PointFromText('POINT (35.691147 139.702084)')) d FROM `cache_fs_search` WHERE MBRWithin(latlng, GeomFromText('POLYGON (( 35.692047 139.701184, 35.692047 139.702984, 35.690247 139.702984, 35.690247 139.701184, 35.692047 139.701184))')) AND distance_in_meter(latlng, PointFromText('POINT (35.691147 139.702084)')) < 100 •POLYGONでは、バウンディングボックスの4頂点の座標を一周り指定。始点と終点 で同じ頂点を指定するので、合計5つの座標を渡す。 •WHERE句ではまずMBRWithin関数により、latlngがバウンディングボックス内にある かが判定され、その上でdistance_in_meter関数により半径100mの円内にあるかの判 定が実行。 • 検索SQL
  17. SELECT cache_id, x(latlng) as lat, y(latlng) as lng, result, distance_in_meter(latlng,

    PointFromText('POINT (35.691147 139.702084)')) d FROM `cache_fs_search` WHERE MBRWithin(latlng, GeomFromText('LINESTRING (35.692047 139.701184, 35.690247 139.702984)')) AND distance_in_meter(latlng, PointFromText('POINT (35.691147 139.702084)')) < 100 • MBRWithin関数に渡すバウンディングボックスは、 POLYGONではなく対角線を表すLINESTRINGを渡すことに より、同じ結果を得ることが出来る。 • もう少し簡潔にできる
  18. 次回 sqrt(x*x+y*y)+3*cos(sqrt(x*x+y*y))+5 from -20 to 20 or WebStorage