IP アドレスに基づいて、かなり大きな IP/City (3,000,000 行以上) テーブルをクエリしようとしています。ソース IP アドレスは 127.0.0.1 などのドット表記であり、テーブルには 2130706433 などの整数として格納された 2 つのフィールドがあります。
select get_ip_integer('74.253.103.98') ,icb.*,icl.*
from ip_city_block icb, ip_city_location icl
where get_ip_integer('74.253.103.98') between icb.startipnum and icb.endipnum and
icl.locid = icb.locid;
このクエリは、かなり高速な DB で 4 ~(4.33) 秒以上かかります。次のクエリには .062 秒かかります。
select 1258121058,icb.*,icl.*
from ip_city_block icb, ip_city_location icl
where icb.startipnum <= 1258121058 and icb.endipnum >= 1258121058 and
icl.locid = icb.locid;
唯一の違いは、関数 get_ip_integer を関数が返す値に置き換えたことです。私が行っていたのが 1 つのルックアップだけだった場合、2 番目のクエリを実行してそれで完了しますが、そうではありません。
実際には、ドット形式の多くの IP アドレスを含む別のテーブルに参加したいのですが、そうすると永遠にかかります。楽しみのために私も試しました。
select ip_integer ,icb.*,icl.*
from (select get_ip_integer('74.253.103.98') ip_integer from dual),ip_city_block icb, ip_city_location icl
where icb.startipnum <= ip_integer and icb.endipnum >= ip_integer and
icl.locid = icb.locid;
これにも約4.33秒かかりました。
問題は、get_ip_integer 関数を強制的に 1 回だけ実行させ、その結果を比較に使用するにはどうすればよいかということです。
関数を Deterministic に更新しましたが、元のクエリでは役立つように見えましたが、より複雑なクエリはまだ使用できず、パフォーマンスが低下しています。ここにあります;
SELECT COUNTRY, REGION,CITY, WEBLOG_USERID, WEBLOG_IP, WEBLOG_COUNT
FROM (
select WEBLOG_USERID,WEBLOG_IP,get_ip_integer(WEBLOG_IP) ip_integer,count(*) WEBLOG_COUNT
from weblog
where weblog_date > '20130217'
group by WEBLOG_USERID,weblog_ip
),ip_city_block icb, ip_city_location icl
where ip_integer between icb.startipnum and icb.endipnum and icl.locid = icb.locid
ORDER BY 1,2,3;
これについて何か考えはありますか?
自分で少し考えた後、私はこれを思いつきましたが、驚くほど速くはありませんが、許容範囲です。
SELECT COUNTRY, REGION,CITY, WEBLOG_USERID, WEBLOG_IP, WEBLOG_COUNT
FROM (
select WEBLOG_USERID,WEBLOG_IP, count(*) WEBLOG_COUNT
from weblog
where weblog_date > '20130000'
group by WEBLOG_USERID,weblog_ip
),ip_city_block icb, ip_city_location icl
where get_ip_integer(WEBLOG_IP) between icb.startipnum and icb.endipnum and icl.locid = icb.locid
ORDER BY 1,2,3;