IPはテキストアドレスではなく、数値IDであることに注意してください。私も同様の状況にあり(geo-ipルックアップを実行しています)、すべてのIPアドレスを整数として保存すると(たとえば、私のIPアドレスは192.115.22.33なので、3228767777として保存されます)、IPをルックアップできます。右シフト演算子を使用して簡単に。
これらすべてのタイプのルックアップの欠点は、インデックスの恩恵を受けることができず、ルックアップを実行するたびに全表スキャンを実行する必要があることです。上記のスキームは、CIDRネットワークのネットワークIPアドレス(範囲の開始)とブロードキャストアドレス(範囲の終了)の両方を格納することで改善できます。たとえば、192.168.1.0 / 24を格納するには、2つを格納できます。列:
network broadcast
3232235776, 3232236031
そして、あなたはそれをあなたがするだけで一致させることができます
SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast
これにより、CIDRネットワークをデータベースに保存し、迅速な数値インデックスを利用して、それらをIPアドレスと迅速かつ効率的に照合できます。
以下の説明からのメモ :
MySQL 5.0には、「インデックスマージ交差 "これにより、次の場合に限り、そのようなクエリを高速化できます(そして全表スキャンを回避できます)。
- クエリの列と正確に一致する複数列のインデックスが順番にあります。したがって、上記のクエリの例では、インデックスは
(network, broadcast)
である必要があります。 。 - すべてのデータをインデックスから取得できます。これは
COUNT(*)
にも当てはまります 、ただし、SELECT * ... LIMIT 1
には当てはまりません 。
MySQL 5.6には、MRRと呼ばれる最適化が含まれており、これにより全行の取得も高速化されますが、これはこの回答の範囲外です。