2011-09-25 13 views
5

私はInnoDB MySql Geo IDテーブルを100万行以上持っています。一種類のみのクエリがありますこのMySQLテーブルを1つのクエリでさらに最適化する方法

CREATE TABLE `geoid` (
    `start_ip` int(11) NOT NULL, 
    `end_ip` int(11) NOT NULL, 
    `city` varchar(64) NOT NULL, 
    `region` char(2) NOT NULL, 
    PRIMARY KEY (`start_ip`,`end_ip`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

このテーブルに対して実行しました::テーブルの構造はこれですこのクエリは、超遅いが、信じられないほど高速ではないではありません〜0.4228秒、程度かかり

SELECT city, region FROM geoid WHERE 1259650516 BETWEEN start_ip AND end_ip 

エーテル。

私の質問は:どのように私はさらに、この単一のクエリのための私のテーブルを最適化することができますか?

は、私は、次のことを試してみました:

  1. 変更のMyISAMのストレージエンジンは、これは、クエリが約1.9秒かかりました。
  2. は 'geoid.start_ip < = 1259650516と1259650516 < = geoid.end_ip' WHEREステートメントを使用します。しかし、それは0.4秒の代わりに約0.5秒かかる。

私はそれを小さくするテーブルからすべての無用の行を削除しました。私はすべて100万行が必要です。

UPDATE/SOLUTION以下の記事へ

おかげで、ここで私は、この問題を修正するために何をしたかです。 (単に興味のある誰のためにこの答えを完了するために)

私は上記の表に新しい列を追加しました:

ALTER TABLE `geoid` ADD `geoip` LINESTRING NOT NULL 

を私はその後、start_ipから地理データを新しい列を充填し

GeomFromText(CONCAT('LINESTRING(', start_ip, ' -1, ', end_ip, ' 1)')) 
をend_ip私はすべて、そこから新しい列

CREATE SPATIAL INDEX geoip_index ON geoid(geoip); 

に空間索引を作成し

クエリを次のように変更する必要があります。

SELECT city, region FROM geoid WHERE MBRContains(geoip, GeomFromText(CONCAT('POINT(', 1259650516, ' 0)'))); 

そして完了しました。これにより、クエリーが0.42秒から0.0003秒にダウンしました!!!!!!!

私はこのINDEXが大好きです。ありがとうございました。それが役に立てば幸い。

+0

あなたは' SPATIAL'インデックスを作成した上で一つのインデックスを作成しますか? – Quassnoi

+0

まずそれをMyISAMに変換しました。 – RonSper

答えて

3

end_ipにインデックスを追加してみてください。これにより、照会が2倍ほど速くなる場合があります。 this articleで説明したように

は、はるかに優れてもパフォーマンスのためには、空間インデックスを使用する必要があります。

+1

プライマリに加えて?同様に:PRIMARY KEY( 'start_ip'、' end_ip')、 KEY 'start_ip'(' start_ip')、 KEY 'end_ip'(' end_ip')。それは何も変わらなかった。 – RonSper

+0

@Ron Sper:すべてのケースでクエリの処理速度が向上するわけではなく、他のケースでは比較的スピードアップしているだけです。パフォーマンスをさらに向上させたい場合は、SPATIALインデックスを検討することをお勧めします。この記事を参照してください:http://explainextended.com/2009/09/29/adjacency-list-vs-nested-sets-mysql/しかし、それは初心者のためではありません。 –

+1

WOW、thats perfect。それはまさに私が望んでいたものです。ありがとうございました。 – RonSper

0

クエリに含まれるすべてのフィールドにインデックスを作成してみます。この特定の場合には `InnoDB`テーブルの上に二つのフィールド(start_ipとend_ip)