我在mysql中,现在加入了postgres,我有一张桌子,每天最多可以获得300,000条新记录,但也有很多读取。我认为2列是理想的索引:纬度和经度我知道postgres有不同类型的索引,我的问题是哪种类型的索引最适合具有多个写入和读取的表?这是读取的查询
SELECT p.fullname,s.post,to_char(s.created_on, 'MON DD,YYYY'),last_reply,s.id,
r.my_id,s.comments,s.city,s.state,p.reputation,s.profile_id
FROM profiles as p INNER JOIN streams as s ON (s.profile_id=p.id) Left JOIN
reputation as r ON (r.stream_id=s.id and r.my_id=?) where s.latitudes >=?
AND ?>= s.latitudes AND s.longitudes>=? AND ?>=s.longitudes order by
s.last_reply desc limit ?"
如您所见,where子句中的2列是纬度和经度
答案 0 :(得分:3)
PostgreSQL的point
data type有很多operators得到了gist
index的良好支持。因此,如果可能的话,请更改您的表格定义,以使用point
而不是2 float
。
插入point
数据非常简单,只需对列使用point(longitudes, latitudes)
,而不是将这两个值放在不同的列中。与获取数据相同:lnglat[0]
是经度,lnglat[1]
是纬度。
索引将是这样的:
CREATE INDEX idx_mytable_lnglat ON streams USING gist (lnglat pointops);
还有box
data type,这对于对所有参数进行分组非常有用,并且在gist
索引中对包中的点进行了高度优化。
如果表格中有point
,并且要搜索box
,则您的查询会缩减为:
SELECT p.fullname, s.post, to_char(s.created_on, 'MON DD,YYYY'), last_reply, s.id,
r.my_id, s.comments, s.city, s.state, p.reputation, s.profile_id
FROM profiles AS p
JOIN streams AS s ON (s.profile_id = p.id)
LEFT JOIN reputation AS r ON r.stream_id = s.id AND r.my_id = ?
WHERE s.lnglat && box(?, ?, ?, ?)
ORDER BY s.last_reply DESC
LIMIT ?;
短语s.lnglat && box(?, ?, ?, ?)
表示"列lnglat的值与(#含义:在里面)框#34;重叠。
答案 1 :(得分:2)
如果对纬度或经度列进行排序,您可能希望使用B树索引。
关于索引的Postgres文档页面:
B树可以处理可以分类为某种排序的数据的相等和范围查询。特别是,只要使用[大于/小于类型的运算符]
之一进行比较,每当索引列涉及索引列时,PostgreSQL查询计划器就会考虑使用B树索引。
您可以阅读有关指数here的更多信息。
编辑:如果您需要在纬度和经度上进行索引,某些G *索引看起来可能有用,因为它们似乎允许多维(例如2d)索引。
Edit2:为了真正创建索引,你想要做的事情(尽管你可能需要更改表名来满足你的需求):
CREATE INDEX idx_lat ON s(latitudes);
请注意,B树索引是默认的,因此您不需要指定类型。
详细了解索引创建here。