ホームページ > バックエンド開発 > PHPチュートリアル > ブロードバンド IP アドレス クエリ IP アドレス クエリにおける PHP 二分法の適用

ブロードバンド IP アドレス クエリ IP アドレス クエリにおける PHP 二分法の適用

WBOY
リリース: 2016-07-29 08:38:35
オリジナル
1262 人が閲覧しました

データベースにはおそらく数十万の IP レコードが保存されており、レコード セットは次のとおりです:
+----------+----------+---------- ----- +---------+-----------+----------+--------+
|国 ID | 都市 ID |
+----------+-----------+--- ----- -+------+------+ 0 | 0 | | 16754431 | 50331648 | 3 | 0 | 678297 59 | 3 0 0 | -----+----------+------+----------+
このクエリを実行するには、次の SQL を使用する必要があります:
$sql = 'SELECT * FROM i_m_ip WHERE ip_begin <= $client_ip AND ip_end >= $client_ip'; このような検索は明らかに行われません。たとえインデックスを使用したとしても、MySQL のクエリ効率が 1 秒あたり 500 回を超える可能性は低く、同時実行の最適化をたくさん行いましたが、最終的な平均クエリ効率は 1 秒あたり 200 回程度しかなく、これは本当に頭の痛い問題でした。 。当初はInnocence IPライブラリの検索手法を利用することも考えましたが、アルゴリズムにずっと抵抗があり、二分法は難しいと思っていたため、利用するまでは至りませんでした。仕方なく、結局二分法でIPアドレスを取得する方法を実現しました。
上の表から、IP ライブラリは 0 から 4294967295 までの連続値であることがわかります。この値を分離して保存すると、数百ギガバイトのデータが存在するため、インデックスを使用する方法がありません。ハッシュする。最終的に、データベースの検索はやめて、PHP を使用してこれらをバイナリ ストレージに変換しました。 IP の開始と終了の長さが 4 バイトの長整数であることがわかります。次の国 ID、州 ID などは 2 バイトの短整数を使用して格納できます。データは 1 行に合計 18 個あります。バイト、合計 31 万個のデータを合計しても、最大 5M にすぎません。具体的な IP ライブラリ生成コードは次のとおりです:
/*
IP ファイル形式:
3741319168 3758096383 182 0 0 0 0
3758096384 3774873599 3 0 0 0 0
37748736 00 4026531839 182 0 0 0 0
4026531840 4278190079 182 0 0 0 0
4294967040 4294967295 312 0 0 0 0
*/
set_time_limit(0);
$fp = fopen("./ ip.dat ", 'ab');
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle);
$buffer = トリム($buffer);
$バッファ =explode ("t", $buffer);
foreach ($buffer as $key => $value) {
$buffer[$key] = (float)rim($value);
$str = Pack( ' L', $buffer[0]);
$str .= パック('L', $buffer[1]);
$str .= パック('S', $buffer[2]); . = パック('S', $buffer[3]);
$str .= パック('S', $buffer[4]); ;
$str .= Pack('S', $buffer[6]); fwrite($fp, $str); というように、バイナリメソッドを使用して IP 情報を取得するのが簡単です。 , $fp) {
fseek($fp, 0);
$begin = 0;
$begin_ip = implode('', unpack('L', fread($fp, 4)));
fseek($fp, $end - 14);
$end_ip = implode('' , unpack('L', fread($fp, 4))); = sprintf( '%u'、$ begin_ip); );
', unpack('S', fread($fp, 2))); 4] = implode('', unpack('S', fread($fp, 2)));Le $ MIDDLE_SEEK = CEIL (($ End-$ Begin)/18)*18+$ Begin
Fseek ($ FP, $ Middle_seek) ' , fread($fp, 4))); '%u', $middle_ip);
if ($ip >= $middle_ip) {
$begin = $middle_seek; } else {
$end = $middle_seek; while (true); 30W 行データの二分法このメソッドは、正確な IP 情報を見つけるために最大約 7 (2^7) 回繰り返すだけで済みます。当初、取得を高速化するために ip.dat をメモリに置きたかったのですが、後で文字列位置決め関数の効率がファイル ポインターのオフセット位置決めと同じ桁ではないことがわかりました。 IP ライブラリを保存するためにメモリを使用します。
この実装により、IP 検索の効率が 100 倍近く向上しました。それ以降、WEB アプリケーションではアルゴリズムは重要ではないという概念が完全に払拭されました。実際、これを達成するために、私も最初は純粋な形式で IP ライブラリを生成し、Discuz の IP クエリ機能を使用してそれを検索するのを手伝ってほしいと Jinhu にアドバイスを求めましたが、彼は私を助けることを拒否しました。そして最終的に私のこの実践と学習を作成しました。場合によっては、自分自身に求めるよりも、他人に求める方が良い場合があります。

上記では、ブロードバンド IP アドレス クエリの内容を含め、IP アドレス クエリにおけるブロードバンド IP アドレス クエリと PHP の二項対立の応用を紹介しました。PHP チュートリアルに興味のある友人に役立つことを願っています。


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート