在表上创建空间索引所需的权限,对于这个BOL 说:
需要对表或视图具有 ALTER 权限。用户必须是 sysadmin 固定服务器角色或 db_ddladmin 和 db_owner 固定数据库角色的成员。
但是,我发现单独的Alter 权限足以在表上创建空间索引。(没有服务器系统管理员权限)
我在下面创建的测试:(运行每个批次以了解发生了什么)
USE adventureworks;
GO
/* Start these scripts with a priveledged account */
CREATE TABLE employees
(employeedid INT PRIMARY KEY IDENTITY(1,1),
empaddress GEOGRAPHY
)
INSERT INTO employees VALUES(geography::STGeomFromText('LINESTRING(47.656 -12.360, 47.656 -12.343)', 4326))
GO
/* Create our test SQL account with limited access = no securables yet */
CREATE LOGIN LimitedPerms WITH Password = 'pass';
CREATE USER LimitedPerms FOR LOGIN LimitedPerms;
GO
EXEC AS …Run Code Online (Sandbox Code Playgroud) PostGIS 提供了两个点构造函数
ST_MakePoint(x,y,[z,[m]])ST_Point(x,y)或不支持 3DZ 或 4D 的兼容版本MySQL 支持 Point(x,y)
在 SQL Server 中,有没有先从两个数字输入或实数构造一个点而不先从文本开始?
我在“创建、构造和查询几何实例”的文档中没有看到采用数字的构造函数。
PostGIS 提供了一个名为ST_MakeLine(pt1,pt2). 它非常适合构建线条。MySQL 对LineString(pt1,pt2). 什么叫 SQL Server 模拟,它需要两个点并构造一个 LineString?
我查了一下LineString,但没有看到提到它。
这是一个关于 dbfiddle 的测试用例。
样本数据,
CREATE TABLE #tmp (
pt1 geometry,
pt2 geometry,
);
INSERT INTO #tmp(pt1,pt2) VALUES
(geometry::Point(1,1,4326), geometry::Point(2,2,4326)),
(geometry::Point(2,2,4326), geometry::Point(5,5,4326)),
(geometry::Point(3,3,4326), geometry::Point(4,4,4326)),
(geometry::Point(4,4,4326), geometry::Point(3,3,4326)),
(geometry::Point(5,5,4326), geometry::Point(4,4,4326));
Run Code Online (Sandbox Code Playgroud)
询问
SELECT pt1, pt2
'My Line' AS line -- what goes here
FROM #tmp;
Run Code Online (Sandbox Code Playgroud)
我希望“My Line”成为LineString.
pt1 pt2 line
POINT (1 1) POINT (2 2) My Line
POINT (2 2) POINT …Run Code Online (Sandbox Code Playgroud) 我有一些表,其中包含存储为 lat long 对的属性的事务。(然后在我的示例架构中有更多的列和数据点)。
一个常见的请求是查找特定点 X 英里范围内发生的交易,并且只检索附近每个房产发生的 5 个最近的交易。
为了完成这项工作,我决定添加一个视图来封装最新的逻辑:
create or alter view dbo.v_example
with schemabinding as
select example_id
,transaction_dt
,latitude
,longitude
,latlong
,most_recent= iif(row_number() over (partition by latitude,longitude order by transaction_dt desc) < 5,1,null)
from dbo.example;
Run Code Online (Sandbox Code Playgroud)
所以一个查询可能看起来像这样:
create or alter view dbo.v_example
with schemabinding as
select example_id
,transaction_dt
,latitude
,longitude
,latlong
,most_recent= iif(row_number() over (partition by latitude,longitude order by transaction_dt desc) < 5,1,null)
from dbo.example;
Run Code Online (Sandbox Code Playgroud)
不幸的是,当我通过视图查询时,SQL Server 不想使用空间索引。如果我删除schemabinding并尝试在视图上添加提示,我会发现查询处理器无法创建计划。
如何封装逻辑并仍然让它使用我的空间索引?
该表要大得多,扫描它然后进行聚集索引查找然后逐点查找要慢得多。
我遇到了一个无法解释的 MSSQL 地理问题。假设我在数学上受到挑战,但似乎以下点不应与以下多边形相交:
DECLARE @t_point geography;
DECLARE @t_polygon geography;
set @t_polygon = geography::STPolyFromText('POLYGON((1 1, 5 5, 5 0, 1 1))', 4326);
set @t_point = geography::Point(0, 0, 4326);
select
@t_polygon.STAsText(),
@t_point.STAsText(),
@t_point.STIntersects(@t_polygon),
@t_polygon.STIntersects(@t_point);
Run Code Online (Sandbox Code Playgroud)
但是,当我执行此操作时,会得到以下结果:
POLYGON ((1 1, 5 5, 5 0, 1 1)) POINT (0 0) 1 1
Run Code Online (Sandbox Code Playgroud)
最后两列都是 1,我期望为 0。空间中 0,0 处的点如何与不接触或包含 0,0 的多边形相交?
-1, -1 与 100, 100 具有相同的行为。
即使我将点更改为完全不同空间中的多边形,MSSQL 也会说它们相交。
set @t_polygon = geography::STPolyFromText('POLYGON((10 10, 50 50, 50 10, 10 10))', 4326);
set @t_point = geography::STPolyFromText('POLYGON((1 1, 5 …Run Code Online (Sandbox Code Playgroud) 我不是数据库设计师,所以我在设计带有 GIS 信息的数据库时遇到了麻烦。目标是创建一个包含大陆、国家、地区(包括州、子地区、省)、城市和城市中的地方的系统。这些元素中的每一个都将包含一些文本信息和相关内容。作为数据库,我们将使用 PostgreSQL 和 PostGIS。
我的问题是,我如何为这个系统设计数据库?我在考虑 2 个表polygons和points,但我不确定这是否是好的思考方式。
实际上我们需要的是一些国家、城市、地区等之间关系的分层基础。该应用程序的主要目标是从许多来源收集关于特定城市、地区、国家等的旅游数据,并将其存储在数据库中。假设我们有一个城市罗马;我们从几个来源收集了一些关于这个城市的信息到数据库中。我们需要知道罗马位于罗马省,拉齐奥地区拉齐奥的次地区拉齐奥,国家意大利。所以系统应该是灵活的,允许我们从现实世界中创建这样的关系。
这就是为什么我会选择两个表:
polygons - 可以存储国家、地区、子地区、省份等。points - 可以存储城市和兴趣点我正在尝试对电路板上零件的放置进行建模。没有任何有意义的限制,我的基本架构如下所示:
create table part (
part_id bigserial primary key,
name text not null,
width double precision not null,
height double precision not null
);
create table board (
board_id bigserial primary key,
width double precision not null,
height double precision not null
);
create table board_part (
board_id bigint not null references board,
part_id bigint not null references part,
position point not null
);
Run Code Online (Sandbox Code Playgroud)
对于b和b2any board_parts,我想强制执行以下约束:
b位于黑板上:
box(b.position, …Run Code Online (Sandbox Code Playgroud)postgresql database-design referential-integrity spatial exclusion-constraint
我有一个带geometry列的表。对于一个记录,只Point存储一个。已创建空间索引,但搜索最近位置的查询不使用此索引,从而导致性能不佳。
示例脚本:
--Create the table
create table Location(
LocationID int not null identity(1,1) primary key,
LocationPoint geometry
)
--add records
declare @counter int =0
WHILE @counter<150000
BEGIN
set nocount on
--select
set @counter =@counter +1
declare @RandomLocation geometry=geometry::Point(RAND() *1000, RAND() *1000, 0)
insert into Location(LocationPoint) values (@RandomLocation)
END
--create index
CREATE SPATIAL INDEX SPATIAL_StructureBE ON dbo.Location(LocationPoint)
USING GEOMETRY_GRID WITH (
BOUNDING_BOX = (xmin = 0.0, ymin = 0.0, xmax = 1000, ymax = 1000),
GRIDS = …Run Code Online (Sandbox Code Playgroud) 我想查询最近邻的空间数据。我正在使用这篇文章,以下查询完美运行:
SELECT TOP 1 [Location].STDistance(@Location)
FROM [DS1]
WHERE [Location].STDistance(@Location) IS NOT NULL
ORDER BY [Location].STDistance(@Location);
Run Code Online (Sandbox Code Playgroud)
问题是我需要为每个MSPID. 我尝试了几件事(使用交叉应用,创建单独的函数等)但没有任何效果。所以,我决定创建一个循环来计算每个MSPID.
SELECT TOP 1 [Location].STDistance(@Location)
FROM [DS1]
WHERE [Location].STDistance(@Location) IS NOT NULL
AND @CurrentMSPID = [MSPID]
ORDER BY [Location].STDistance(@Location);
Run Code Online (Sandbox Code Playgroud)
问题是上面的语句没有使用索引。如果我@CurrentMSPID用一个数字替换使用索引,但是当使用一个变量时,使用聚集索引而不是空间索引。
我尝试了很多选择,唯一有效的是:
OPTION (OPTIMIZE FOR ( @CurrentMSPID = 1001 ))
Run Code Online (Sandbox Code Playgroud)
或者当值是硬编码时。我不能那样做,因为将来这id甚至可能不存在,并且肯定会更改它匹配的行数。
该[DS1]表在[MSPID]列上有主键,在列上有空间索引[Location]。
如何在不使用OPTIMIZE FOR选项的情况下帮助引擎生成更好的执行计划并使用空间索引?
当从表中提取其他数据时(我们MSPID现在正在过滤),引擎似乎无法使用空间索引并执行聚集索引查找。
sql-server sql-server-2012 spatial sql-server-2014 nearest-neighbor
我有一个包含 10,301,390 个 GPS 记录、城市、国家和 IP 地址块的表。我有用户当前的经纬度位置。我创建了这个查询:
SELECT
*, point(45.1013021, 46.3021011) <@> point(latitude, longitude) :: point AS distance
FROM
locs
WHERE
(
point(45.1013021, 46.3021011) <@> point(latitude, longitude)
) < 10 -- radius
ORDER BY
distance LIMIT 1;
Run Code Online (Sandbox Code Playgroud)
这个查询成功地给了我我想要的东西,但它很慢。根据给定的纬度和经度,获得一条记录需要 2 到 3 秒。
我在latitude和longitude列上尝试了 B 树索引,也尝试过,GIST( point(latitude, longitude));但查询仍然很慢。
我怎样才能加快这个查询?
似乎缓慢是由 引起的,ORDER BY但我想获得最短距离,所以问题仍然存在。