3

私は 4 つのソースの IP アドレスを持っています。それらを SQL Server に保存し、発信元の国コードで分類できる範囲を国ごとに除外リストに入れたいと考えています。

このために、2つのテーブルがあります。

IPアドレス範囲国コード

私が知る必要があるのは、このデータがクライアントに返された後、迅速なクエリのためにキャッシュされた場合、返されたデータを格納して範囲内の特定の IP アドレスをクエリするための最良の方法は何かということです。指定した IP アドレスがリストにあるかどうかを知りたいです。

リストがデータベースにある理由は、簡単に保管するためです。

キャッシュしてからクライアントでデータを使用したい理由は、トライ構造の方が IP アドレスの検索が速いと聞いたからです。したがって、データベースからリストを取得し、検索が非常に迅速な構造でキャッシュに保存する必要があると思います。

A) アドレスを格納するための SQL 構造と、b) IP アドレスを検索するためのコードのヘルプ。

これをストレージの側面と組み合わせる方法がわからない検索用のコードアルゴリズムを持つコードプロジェクトソリューションを知っています。

サードパーティのライブラリを使用しないことが理想的です。コードは、独自のサーバー上にある必要があります。

4

7 に答える 7

3

あなたが説明したのとまったく同じように、国ごとにフィルターをかけました。

しかし、しばらく実験した後、SQL ではパフォーマンスの高い方法で実行できないことがわかりました。そのため、このような IP データベース(私が使用しているデータベース) は、この種のデータ用に最適化されているため、はるかに高速なバイナリ データベースを提供します。

彼らははっきりと言う:

SQL データベースにインポートされた CSV データに対して実行されるクエリには、最大で数秒かかる場合があることに注意してください。パフォーマンスが問題になる場合は、バイナリ形式の方がはるかに高速で、1 秒あたり数千回のルックアップを処理できます。

さらに、このデータベースにクエリを実行するためのコードも提供されます。

私はこれをトラフィックが中程度の本番Webサイトで使用し、すべてのリクエストをフィルタリングし、パフォーマンスの問題はありません.

于 2009-01-19T21:13:36.583 に答える
1

IP アドレスが IPV4 であると仮定すると、それらを整数フィールドに格納することができます。2 つのフィールドを作成します。1 つは範囲の下限用、もう 1 つは上限用です。次に、これらの to フィールドにインデックスが付けられていることを確認します。値を検索するときは、値が下限以上で上限以下の場所を検索するだけです。より複雑なものを自分でプログラムしようとする前に、このような単純なものを試してみますが、実際にはそれほど速い結果は得られません。

于 2009-01-19T20:45:31.977 に答える
0

IPv6 アドレスは、8 バイトの符号なし整数 (C# の ulong) にすることができます。

IPv6 アドレスは、提案されている 8 ではなく 128 ビット (16 バイト) です。私は現在、IP 範囲に関してまさにこの問題に取り組んでいます。

パディング文字列または 16 進文字列を試して、< と > の比較のみを行うことを検討しています

于 2009-01-19T21:31:21.853 に答える
0

IPv4 アドレスは、4 バイトの符号なし整数 (C# の uint) として格納できます。IPv6 アドレスは、8 バイトの符号なし整数 (C# の ulong) にすることができます。SQL で適切な幅の列を作成し、それらを取得して変数に格納します。次に、単純な整数演算を使用して、範囲が実際に連続していると仮定して、必要な範囲を確認します。

より複雑な解決策は、より使い慣れたドット四角形構造へのアクセスを提供する IPAddress クラスを作成することですが、内部では、ここにあるものとまったく同じことを行います。

于 2009-01-19T20:44:36.830 に答える
0

私はこれを試みたことがないので、私の答えを一粒の塩で取りますが、ブロックしたいすべてのIPを保存するつもりがない限り、トライは実際にはあなたが望むものではないと思います(範囲またはサブネット/マスクとは対照的に) . btree の方が適していると思います。その場合は、通常のデータベースを使用してください (多くのデータベースは btree または同等の優れたデータ構造で実装されています)。IP の 4 バイトのそれぞれを別の列に保存して、NULL に等しい「ドント ケア」値を持つクラス A/B/C サブネットによる検索を支援しますが、保存できない理由はありません。それを単一の 32 ビット整数列として計算し、数値をクランチしてどの範囲に入る必要があるかを判断します (この場合、マスクアウトされた値を格納するのは少し難しいでしょう)。

于 2009-01-19T20:45:10.743 に答える
0

IPv4 開始アドレスを適切なデータ型で保存すれば、効率的に実行できます。varchar (またはその他の文字列型) は正しくありません。int を使用する必要があります。

IPv4 の場合、IP 番号を十分な大きさの unsigned in に保存し、それを INET_ATON 形式で保存します (これは簡単に生成できます。C# での方法はわかりませんが、難しくはありません)。

次に、データベースが範囲スキャンを実行するように調整することで、IP アドレスがどの範囲に属しているかを簡単かつ効率的に検索できます。

LIMIT (または MSSQL の SELECT TOP 1) を使用すると、レコードが見つかったら停止できます。

SELECT TOP 1 networkidorwhatever, IPNumber, IPNumberUpperBoundOrWhateverYouCallIt 
FROM networks 
WHERE IPNumber <= IPNUMBERTOQUERY ORDER BY IPNumber DESC 

IP 番号以下の最大番号のネットワーク番号を見つける必要があります。その IP アドレスがその範囲内にあるかどうかを判断するのは簡単なチェックです。

IPNumber に従来のインデックスがあれば効率的です。

IPv6 の場合、タイプは異なりますが、原則は同じです。

于 2009-01-19T21:49:38.040 に答える
0

IPv4 の場合、通常、DBA は 4 つの tinyint フィールドを推奨しますが、以前に提供された整数ストレージ ソリューションにより適した範囲を実行しています。その場合、範囲の開始 IP アドレスと終了 IP アドレスを保存します。次に、比較を行うのは簡単なことです。

于 2009-01-20T02:36:18.647 に答える