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`

它实质上会找到一年中的某一天是今天的正负 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 部分放入两次。

我对查询的需求是查找所有name具有一年中的某一天 + 或 - 14 天,并且在给定的纬度/经度对内的 s,然后合计每个的计数。

我对这些东西很愚蠢,所以如果我在做一些愚蠢的事情,请纠正我。多谢你们!

4

1 回答 1

6

重写它,以便您的计算在每个查询中发生一次,而不是通过表达您的谓词使该列不是计算的一部分 而每行发生一次。

例如,这个表达式:

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

这需要 700 万次计算date,可以表示为

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

它只需要 1 次计算,并且进一步允许使用date列上的索引。
仅此更改就会加快您的查询速度。

如果您没有日期索引,请放置一个,您的查询就会飞起来:

create index mytable_date on mytable(`date`);


我不知道是什么MBRCONTAINS,但也尝试重构它,以便列值不是计算的一部分。

于 2012-09-22T19:14:06.220 回答