3

クエリは次のとおりです。

SELECT name, SUM(  `count` ) AS Total
FROM  `identdb` 
WHERE MBRCONTAINS( GEOMFROMTEXT(  'LineString(34.4 -119.9, 34.5 -119.8)' ) , latlng ) 
AND MOD( DAYOFYEAR( CURDATE( ) ) - DAYOFYEAR(  `date` ) +365, 365 ) <=14
OR MOD( DAYOFYEAR(  `date` ) - DAYOFYEAR( CURDATE( ) ) +365, 365 ) <=14
AND MBRCONTAINS( GEOMFROMTEXT(  'LineString(34.4 -119.9, 34.5 -119.8)' ) , latlng ) 
GROUP BY  `name`

基本的に、1年の日が今日の日のプラスマイナス14である行と、latlng空間列が長方形内にある行を検索します。

私のデータベースは次のようになります。

#   Column  Type        Collation   
1   name    varchar(66) utf8_general_ci 
2   count   tinyint(3)
3   date    date    
4   latlng  geometry
5   lat1    varchar(15) latin1_swedish_ci
6   long1   varchar(15) latin1_swedish_ci

Keyname Type    Unique  Packed  Column  Cardinality Collation   Null    Comment
PRIMARY BTREE   Yes No  name    0   A       
                        count   0   A   
                        date    0   A   
                        lat1    0   A   
                        long1   6976936 A   
sp_index SPATIAL    No  No  latlng (32) 0   A

700万件のレコードがあり、クエリには約7秒かかります。事前に感謝します、これをスピードアップする方法がわかりません!

説明:

id  select_type table   type    possible_keys   key     key_len ref  rows       Extra
1   SIMPLE      identdb ALL     sp_index        NULL    NULL    NULL 6976936    Using where; Using temporary; Using filesort

クエリの更新された説明:MBRCONTAINSは、latlng空間ポイントが内側にあるかどうかを比較できる長方形を作成すると思います。日付の部分は、dayofyear+または-14日を検索しています。新年の前後で混乱しないように、モジュラー演算を使用しています。ORを使用しているため、MBRCONTAINSパーツを2回挿入する必要がありました。

nameクエリの私のニーズは、1年の日が+または-14日で、指定された緯度/経度のペア内にあるすべてのを見つけて、それぞれのカウントを合計することです。

私はこのようなことで愚かですので、私が何か愚かなことをしているなら私を訂正してください。みんなありがとう!

4

1 に答える 1

6

列が計算の一部にならないように述語を表現することで、 ごとに 1 回ではなく、queryごとに 1 回計算が行われるように書き直してください。

たとえば、次の式:

MOD( DAYOFYEAR( CURDATE( ) ) - DAYOFYEAR(  `date` ) +365, 365 ) <= 14

で 700 万回の計算が必要でありdate、次のように表すことができます。

`date` between SUBDATE( CURDATE( ), 14) and ADDDATE( CURDATE( ), 14)

dateこれにより、計算が 1 回だけ必要になり、さらに列のインデックスを使用できるようになります。
その変更だけで、クエリが高速化されます。

日付にインデックスがない場合は、インデックスを付けてクエリを実行します。

create index mytable_date on mytable(`date`);


何が原因かわかりませんがMBRCONTAINS、列の値が計算に含まれないようにリファクタリングしてみてください。

于 2012-09-22T19:14:06.220 に答える