私の解決策には1つの警告があります:
1) このソリューションの注意点は、イベント テーブルに MyISAM エンジンを使用する必要があることです。MyISAM を使用できない場合、空間インデックスでは MyISAM のみがサポートされているため、このソリューションは機能しません。
したがって、上記が問題にならないと仮定すると、以下が機能し、良好なパフォーマンスが得られるはずです。
このソリューションは、MySQL の Spatial Data のサポートを利用します (こちらのドキュメントを参照してください)。空間データ型はさまざまなストレージ エンジンに追加できますが、必要なパフォーマンスを得るために必要な空間 R ツリー インデックス (こちらのドキュメントを参照) では MyISAM のみがサポートされています。もう 1 つの制限は、空間データ型は数値データでのみ機能するため、この手法を文字列ベースの範囲クエリで使用できないことです。
空間タイプがどのように機能するか、および空間インデックスがどのように役立つかの背後にある理論の詳細については説明しませんが、GeoIP ルックアップに空間データ タイプとインデックスを使用する方法については、 Jeremy Cole の説明を参照してください。また、生のパフォーマンスが必要で、ある程度の精度が必要な場合は、コメントがいくつかの有用なポイントと代替案を提起しているため、コメントを参照してください。
基本的な前提は、始点/終点を取得し、そのうちの 2 つを使用して、xy グリッド上の 0,0 を中心とする長方形の各コーナーに 1 つずつ、4 つの異なるポイントを作成し、空間をすばやく検索できることです。気になる特定の時点が長方形内にあるかどうかを判断するためのインデックス。前述のように、これがどのように機能するかのより完全な概要については、Jeremy Cole の説明を参照してください。
特定のケースでは、次のことを行う必要があります。
1) テーブルを MyISAM テーブルに変更します (MyISAM に関連するトランザクションの欠如やテーブルのロック動作など、このような変更の結果を十分に認識していない限り、これを行うべきではないことに注意してください)。
alter table events engine = MyISAM;
2) 次に、空間データを保持する新しい列を追加します。完全な長方形を保持できるようにする必要があるため、ポリゴン データ型を使用します。
alter table events add column time_poly polygon NOT NULL;
3) 次に、新しい列にデータを入力します (テーブル イベントに更新または挿入するプロセスは、新しい列にも入力されるように変更する必要があることに注意してください)。開始範囲と終了範囲は時間であるため、unix_timestamp 関数を使用して数値に変換する必要があります (仕組みについては、こちらのドキュメントを参照してください)。
update events set time_poly := LINESTRINGFROMWKB(LINESTRING(
POINT(unix_timestamp(start_time), -1),
POINT(unix_timestamp(end_time), -1),
POINT(unix_timestamp(end_time), 1),
POINT(unix_timestamp(start_time), 1),
POINT(unix_timestamp(start_time), -1)
));
4) 次に、空間インデックスをテーブルに追加します (前述のように、これは MyISAM テーブルでのみ機能し、「エラー 1464 (HY000): 使用されているテーブル タイプは SPATIAL インデックスをサポートしていません」というエラーが発生します)。
alter table events add SPATIAL KEY `IXs_time_poly` (`time_poly`);
5) 次に、データのクエリを実行するときに空間インデックスを利用するために、次の選択を使用する必要があります。
SELECT *
FROM events force index (IXs_time_poly)
WHERE MBRCONTAINS(events.time_poly, POINTFROMWKB(POINT(unix_timestamp('2009-02-18 16:27:12'), 0)));
強制インデックスは、MySQL がルックアップにインデックスを使用することを 100% 確実にするためにあります。すべてがうまくいった場合、上記の select で Explain を実行すると、次のようなものが表示されます。
mysql> explain SELECT *
-> FROM events force index (IXs_time_poly)
-> on MBRCONTAINS(events.time_poly, POINTFROMWKB(POINT(unix_timestamp('2009-02-18 16:27:12'), 0)));
+----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+
| 1 | SIMPLE | B | range | IXs_time_poly | IXs_time_poly | 32 | NULL | 1 | Using where |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+
1 row in set (0.00 sec)
between 句と比較した場合のこの方法のパフォーマンス上の利点の詳細については、Jeremy Cole の分析を参照してください。
ご不明な点がございましたら、お知らせください。
ありがとう、
-ディピン