sql >> データベース >  >> RDS >> Mysql

MySQL:より高速なIP範囲クエリを作成する方法は? GeoIP

    私は同様の問題に取り組んでいました。そこでは、約400万のIP範囲を持つデータベースを検索し、スキャンされた行の数を400万から約5に減らす優れたソリューションを見つけました(IPによって異なります):

    このSQLステートメント:

    SELECT id FROM geoip WHERE $iplong BETWEEN range_begin AND range_end 
    

    に変換されます:

    SELECT id FROM geoip WHERE range_begin <= $iplong AND range_end >= $iplong 
    

    問題は、MySQLが'range_begin <=$ iplong'のすべての行を取得し、'range_end> =$iplong'の場合にスキャンする必要があることです。この最初のAND条件(range_begin <=$ iplong)は約200万行を取得し、range_endが一致するかどうかをすべてチェックする必要があります。

    ただし、これは1つのAND条件を追加することで大幅に簡略化できます:

    SELECT id FROM geoip WHERE range_begin <= $iplong AND range_begin >= $iplong-65535 AND range_end >= $iplong 
    

    ステートメント

    range_begin <= $iplong AND range_begin >= $iplong-65535
    

    range_beginが$iplong-65535と$iplongの間にあるエントリのみを取得します。私の場合、これにより、取得される行の数が4Mioから減少しました。約5になり、スクリプトの実行時間は数分から数秒に短縮されました。

    65535に関する注意 :これは私のテーブルの場合、range_beginとrange_endの間の最大距離です。つまり、すべての行で(range_end-range_begin)<=65535です。 IP範囲が大きい場合は、65535を増やす必要があります。IP範囲が小さい場合は、この定数を減らすことができます。この定数が大きすぎる場合(たとえば40億)、クエリ時間を節約できません。

    このクエリでは、range_beginのインデックスのみが必要です。



    1. 2つのSQLLEFTJOINSが誤った結果を生成する

    2. Python FlaskとMySQLを使用してゼロからWebアプリを作成する:パート4

    3. パフォーマンスが低下し始める前に、MySQLデータベースはどのくらい大きくなることができますか

    4. 小文字でのMySQL自動変換