[转]如何监测谁用了SQL Server的Tempdb空间

Tempdb 系统数据库是一个全局资源,供连接到 SQL Server 实例的所有用户使用。在现在的SQL Server里,其使用频率可能会超过用户的想象。如果Tempdb空间耗尽,许多操作将不能完成。

作为一个支持工程师,会被经常问到象“我的Tempdb为什么这么大?”“是谁把我的Tempdb空间用完的?”在SQL 2000的时候,这个问题很难回答。好在SQL 2005以后,引入了一张新的管理视图:sys.dm_db_file_space_usage。通过查询这张视图,能了解tempdb的空间使用情况,能知道tempdb的空间是被哪一块对象使用掉的,是用户对象(user_object_reserved_page_count字段),还是系统对象(internal_object_reserved_page_count字段),还是版本存储区(version_store_reserved_page_count字段)。

在讨论Tempdb空间使用之前,我们先简单介绍一下通常什么操作会大量使用Tempdb。在SQL 2005和SQL 2008里,使用Tempdb空间的远远不止是临时表。常见的使用对象有:

用户对象(user_object_reserved_page_count)

用户对象由用户显式创建。这些对象可以位于用户会话的作用域中,也可位于创建对象所用例程的作用域中。 可以是存储过程、触发器或用户定义函数。 用户对象可以是下列项之一:

  • 用户定义的表和索引
  • 系统表和索引
  • 全局临时表和索引
  • 局部临时表和索引
  • table 变量
  • 表值函数中返回的表

内部对象(internal_object_reserved_page_count)

内部对象是根据需要由 SQL Server 数据库引擎创建的,用于处理 SQL Server 语句。 内部对象可以在语句的作用域中创建和删除。 内部对象可以是下列项之一:

  • 用于游标。
  • 用于哈希联接或哈希聚合操作的查询。
  • 某些 GROUP BY、ORDER BY 或 UNION 查询的中间排序结果。

版本存储(version_store_reserved_page_count)

版本存储区主要用来支持Snapshot事务隔离级别,以及SQL 2005以后推出的一些其他提高数据库并发度的新功能。

由此可见,光从用户发过来的语句本身,是很难判断这个连接的操作是否会使用Tempdb的。一个典型的例子,就是某些查询。如果表格上有良好的索引做支持,SQL Server不需要做哈希联接(Hash Join),那这个查询就不会用Tempdb。反之,如果表格很大,又没有好的索引,那Tempdb使用量就可能不小。

tempdb空间使用的一大特点,是只有一部分对象,例如用户创建的临时表、table变量等,可以用sys.allocation_units 和sys.partitions这样的管理视图来管理。许多内部对象和版本存储在这些管理视图里没有体现。所以,sp_spaceused的结果和真实使用会有很大差异,tempdb的空间使用是不能用sp_spaceused来跟踪的。必须借助sys.dm_db_file_space_usage这样的管理视图和管理函数,才能看到全貌。

下面以一个实例,讨论一下如何用DBCC命令、管理视图(DMV)以及管理函数(DMF)来监视是什么语句正在使用tempdb。

为了使结果简单,我们在测试之前先把SQL Server重起一次。

然后我们在Management Studio里做一个连接(连接A),将下面语句输入。这些语句会使用tempdb的空间。

[sql] view plaincopyprint?

  1. USE [My_Test_DB]
  2. go
  3. SELECT  GETDATE()
  4. go
  5. SELECT  *
  6. INTO    #MyOrderSource
  7. FROM   OrderSource AS o
  8. -- 创建一个temp table,OrderSource 是一个很大的表这样效果更明显
  9. -- 这个操作应该会申请user objects page
  10. go
  11. WAITFOR DELAY ‘0:0:2‘
  12. SELECT  GETDATE()
  13. go
  14. DROP TABLE #MyOrderSource
  15. -- 删除一个temp table
  16. -- 这个操作后user object page数量应该会下降
  17. go
  18. WAITFOR DELAY ‘0:0:2‘
  19. SELECT  GETDATE()
  20. go
  21. SELECT TOP 100000*
  22. FROM    OrderSource AS o
  23. JOIN shippingOrder AS s ON o.OrderId=b.OrderId
  24. -- 这里做了一个比较大的join.
  25. -- 应该会有internal objects的申请.
  26. go
  27. SELECT  GETDATE()
  28. -- join 语句做完以后internal objects page数目应该下降
USE [My_Test_DB]
go

SELECT  GETDATE()
go

SELECT  *
INTO    #MyOrderSource
FROM   OrderSource AS o

-- 创建一个temp table,OrderSource 是一个很大的表这样效果更明显
-- 这个操作应该会申请user objects page
go

WAITFOR DELAY ‘0:0:2‘

SELECT  GETDATE()
go

DROP TABLE #MyOrderSource

-- 删除一个temp table
-- 这个操作后user object page数量应该会下降

go

WAITFOR DELAY ‘0:0:2‘

SELECT  GETDATE()
go

SELECT TOP 100000*
FROM    OrderSource AS o
JOIN shippingOrder AS s ON o.OrderId=b.OrderId

-- 这里做了一个比较大的join.

-- 应该会有internal objects的申请.

go

SELECT  GETDATE()

-- join 语句做完以后internal objects page数目应该下降

那用什么脚本可用监视上面的行为呢?下面的脚本就可以监视和发现当前的Tempdb使用者。这个脚本需要在使用tempdb的语句开始运行之前开始。(读者当然可以根据自己的喜好,修改这个脚本。)

脚本首先用“dbcc showfilestats”语句查询当前tempdb的总体使用量。再查询sys.dm_db_file_space_usage视图,得到Tempdb里当前总共有多少用户对象、内部对象、以及版本存储。然后查询sys.dm_db_session_space_usage和sys.dm_exec_sessions,找到当前使用Tempdb的所有连接。最后通过sys.dm_exec_sql_text,找到这些连接正在运行的语句。

[sql] view plaincopyprint?

  1. USE tempdb
  2. -- 每隔1秒钟运行一次,直到用户手工终止脚本运行
  3. WHILE 1 = 1
  4. BEGIN
  5. -- Query 1
  6. -- 从文件级看tempdb使用情况
  7. DBCC showfilestats
  8. -- Query 2
  9. -- 返回所有做过空间申请的session信息
  10. SELECT  ‘tempdb‘ AS database_name , GETDATE() AS Time , SUM(user_object_reserved_page_count)/128. AS user_objects_mb ,
  11. SUM(internal_object_reserved_page_count)/128. AS internal_objects_mb , SUM(version_store_reserved_page_count)/128. AS version_store_kb ,
  12. SUM(unallocated_extent_page_count)/128. AS freespace_mb
  13. FROM    sys.dm_db_file_space_usage
  14. WHERE   database_id = 2
  15. -- Query 3
  16. -- 这个管理视图能够反映当时tempdb空间的总体分配
  17. SELECT  t1.session_id , t1.internal_objects_alloc_page_count , t1.user_objects_alloc_page_count , t1.internal_objects_dealloc_page_count ,
  18. t1.user_objects_dealloc_page_count , t3.login_time , t3.login_name , t3.host_name , t3.nt_domain , t3.nt_user_name , t3.program_name ,
  19. t3.status , t3.client_interface_name , t3.cpu_time , t3.memory_usage , t3.total_scheduled_time , t3.total_elapsed_time ,
  20. t3.last_request_start_time , t3.last_request_end_time , t3.reads , t3.writes , t3.logical_reads , t3.is_user_process , t3.row_count ,
  21. t3.prev_error , t3.original_security_id , t3.original_login_name , t3.last_successful_logon , t3.last_unsuccessful_logon ,
  22. t3.unsuccessful_logons , t3.group_id
  23. FROM    sys.dm_db_session_space_usage t1 ,
  24. -- 反映每个session累计空间申请
  25. sys.dm_exec_sessions AS t3
  26. -- 每个session的信息
  27. WHERE   t1.session_id = t3.session_id
  28. AND (
  29. t1.internal_objects_alloc_page_count > 0
  30. OR t1.user_objects_alloc_page_count > 0
  31. OR t1.internal_objects_dealloc_page_count > 0
  32. OR t1.user_objects_dealloc_page_count > 0
  33. )
  34. -- Query 4
  35. -- 返回正在运行并且做过空间申请的session正在运行的语句
  36. SELECT  t1.session_id , st.text , GETDATE()
  37. FROM    sys.dm_db_session_space_usage AS t1 ,
  38. sys.dm_exec_requests AS t4
  39. CROSS APPLY sys.dm_exec_sql_text(t4.sql_handle) AS st
  40. WHERE   t1.session_id = t4.session_id
  41. AND t1.session_id > 50
  42. AND (
  43. t1.internal_objects_alloc_page_count > 0
  44. OR t1.user_objects_alloc_page_count > 0
  45. OR t1.internal_objects_dealloc_page_count > 0
  46. OR t1.user_objects_dealloc_page_count > 0
  47. )
  48. -- Query 5
  49. -- 返回正在运行的活动的空间使用情况以及语句内容和执行计划
  50. ;WITH task_space_usage AS (
  51. -- SUM alloc/delloc pages
  52. SELECT session_id,
  53. request_id,
  54. SUM(internal_objects_alloc_page_count) AS alloc_pages,
  55. SUM(internal_objects_dealloc_page_count) AS dealloc_pages
  56. FROM sys.dm_db_task_space_usage WITH (NOLOCK)
  57. WHERE session_id <> @@SPID
  58. GROUP BY session_id, request_id
  59. )
  60. SELECT TSU.session_id,
  61. TSU.alloc_pages * 1.0 / 128 AS [internal object MB space],
  62. TSU.dealloc_pages * 1.0 / 128 AS [internal object dealloc MB space],
  63. EST.text,
  64. -- Extract statement from sql text
  65. ISNULL(
  66. NULLIF(
  67. SUBSTRING(
  68. EST.text,
  69. ERQ.statement_start_offset / 2,
  70. CASE WHEN ERQ.statement_end_offset < ERQ.statement_start_offset THEN 0 ELSE( ERQ.statement_end_offset - ERQ.statement_start_offset ) / 2 END
  71. ), ‘‘
  72. ), EST.text
  73. ) AS [statement text],
  74. EQP.query_plan
  75. FROM task_space_usage AS TSU
  76. INNER JOIN sys.dm_exec_requests ERQ WITH (NOLOCK)
  77. ON  TSU.session_id = ERQ.session_id
  78. AND TSU.request_id = ERQ.request_id
  79. OUTER APPLY sys.dm_exec_sql_text(ERQ.sql_handle) AS EST
  80. OUTER APPLY sys.dm_exec_query_plan(ERQ.plan_handle) AS EQP
  81. WHERE EST.text IS NOT NULL OR EQP.query_plan IS NOT NULL
  82. ORDER BY 3 DESC, 5 DESC
  83. WAITFOR DELAY ‘0:0:1‘
  84. END
USE tempdb                                                               

-- 每隔1秒钟运行一次,直到用户手工终止脚本运行

WHILE 1 = 1
BEGIN                                                                   

-- Query 1
-- 从文件级看tempdb使用情况
DBCC showfilestats                                                 

-- Query 2
-- 返回所有做过空间申请的session信息
SELECT  ‘tempdb‘ AS database_name , GETDATE() AS Time , SUM(user_object_reserved_page_count)/128. AS user_objects_mb ,
        SUM(internal_object_reserved_page_count)/128. AS internal_objects_mb , SUM(version_store_reserved_page_count)/128. AS version_store_kb ,
        SUM(unallocated_extent_page_count)/128. AS freespace_mb
FROM    sys.dm_db_file_space_usage
WHERE   database_id = 2                                                    

-- Query 3
-- 这个管理视图能够反映当时tempdb空间的总体分配
SELECT  t1.session_id , t1.internal_objects_alloc_page_count , t1.user_objects_alloc_page_count , t1.internal_objects_dealloc_page_count ,
        t1.user_objects_dealloc_page_count , t3.login_time , t3.login_name , t3.host_name , t3.nt_domain , t3.nt_user_name , t3.program_name ,
        t3.status , t3.client_interface_name , t3.cpu_time , t3.memory_usage , t3.total_scheduled_time , t3.total_elapsed_time ,
        t3.last_request_start_time , t3.last_request_end_time , t3.reads , t3.writes , t3.logical_reads , t3.is_user_process , t3.row_count ,
        t3.prev_error , t3.original_security_id , t3.original_login_name , t3.last_successful_logon , t3.last_unsuccessful_logon ,
        t3.unsuccessful_logons , t3.group_id
FROM    sys.dm_db_session_space_usage t1 ,
-- 反映每个session累计空间申请
        sys.dm_exec_sessions AS t3
-- 每个session的信息
WHERE   t1.session_id = t3.session_id
        AND (
             t1.internal_objects_alloc_page_count > 0
             OR t1.user_objects_alloc_page_count > 0
             OR t1.internal_objects_dealloc_page_count > 0
             OR t1.user_objects_dealloc_page_count > 0
            )

-- Query 4
-- 返回正在运行并且做过空间申请的session正在运行的语句
SELECT  t1.session_id , st.text , GETDATE()
FROM    sys.dm_db_session_space_usage AS t1 ,
        sys.dm_exec_requests AS t4
CROSS APPLY sys.dm_exec_sql_text(t4.sql_handle) AS st
WHERE   t1.session_id = t4.session_id
        AND t1.session_id > 50
        AND (
             t1.internal_objects_alloc_page_count > 0
             OR t1.user_objects_alloc_page_count > 0
             OR t1.internal_objects_dealloc_page_count > 0
             OR t1.user_objects_dealloc_page_count > 0
            )
-- Query 5
-- 返回正在运行的活动的空间使用情况以及语句内容和执行计划
;WITH task_space_usage AS (
    -- SUM alloc/delloc pages
    SELECT session_id,
           request_id,
           SUM(internal_objects_alloc_page_count) AS alloc_pages,
           SUM(internal_objects_dealloc_page_count) AS dealloc_pages
    FROM sys.dm_db_task_space_usage WITH (NOLOCK)
    WHERE session_id <> @@SPID
    GROUP BY session_id, request_id
)
SELECT TSU.session_id,
       TSU.alloc_pages * 1.0 / 128 AS [internal object MB space],
       TSU.dealloc_pages * 1.0 / 128 AS [internal object dealloc MB space],
       EST.text,
       -- Extract statement from sql text
       ISNULL(
           NULLIF(
               SUBSTRING(
                   EST.text,
                   ERQ.statement_start_offset / 2,
                   CASE WHEN ERQ.statement_end_offset < ERQ.statement_start_offset THEN 0 ELSE( ERQ.statement_end_offset - ERQ.statement_start_offset ) / 2 END
               ), ‘‘
           ), EST.text
       ) AS [statement text],
       EQP.query_plan
FROM task_space_usage AS TSU
INNER JOIN sys.dm_exec_requests ERQ WITH (NOLOCK)
    ON  TSU.session_id = ERQ.session_id
    AND TSU.request_id = ERQ.request_id
OUTER APPLY sys.dm_exec_sql_text(ERQ.sql_handle) AS EST
OUTER APPLY sys.dm_exec_query_plan(ERQ.plan_handle) AS EQP
WHERE EST.text IS NOT NULL OR EQP.query_plan IS NOT NULL
ORDER BY 3 DESC, 5 DESC

WAITFOR DELAY ‘0:0:1‘
END      

在运行这个脚本的连接(连接B)里,我们选择好“ 将结果保存到文本”。先开始运行它,指定输出文件路径。然后,我们再运行连接A(图2)。连接A运行结束后,手工停止连接B的运行。

连接B生成的是一个文本文件。文本里面可以看出tempdb的使用空间有过增长和下降。结果我在这里不做过多的分析,有兴趣的可以尝试一下

如果没有太好的分析,可以创建几个表,然后把查询结果插入到表里面,然后对表进行分析。从而来确定导致你tempdb 暴增的原因。下面附上建表的脚本,供大家参考使用

[sql] view plaincopyprint?

  1. -- 1
  2. -- 创建表 tb_showfilestats 记录 DBCC showfilestats 返回的信息
  3. IF OBJECT_ID(‘tb_showfilestats‘ , ‘U‘) IS NOT NULL
  4. DROP TABLE tb_showfilestats
  5. GO
  6. CREATE TABLE tb_showfilestats
  7. (
  8. id INT IDENTITY(1,1) PRIMARY KEY,
  9. Fileid INT ,
  10. FileGroup INT ,
  11. TotalExtents INT ,
  12. UsedExtents INT ,
  13. Name VARCHAR(100) ,
  14. FILENAME VARCHAR(255)
  15. )
  16. GO
  17. -- 2
  18. -- 创建表 tb_db_file_space_usage 记录 所有做过空间申请的 session 信息
  19. IF OBJECT_ID(‘tb_db_file_space_usage‘ , ‘U‘) IS NOT NULL
  20. DROP TABLE tb_db_file_space_usage
  21. GO
  22. CREATE TABLE tb_db_file_space_usage
  23. (
  24. id INT IDENTITY(1,1) PRIMARY KEY,
  25. database_name VARCHAR(50) ,
  26. InDate DATETIME ,
  27. user_objects_mb DECIMAL(18,4) ,
  28. internal_objects_mb DECIMAL(18,4) ,
  29. version_store_kb DECIMAL(18,4) ,
  30. freespace_mbFILENAME DECIMAL(18,4)
  31. )
  32. GO
  33. -- 3
  34. -- 创建表 tb_db_session_space_usage 记录正在运行的 tempdb 空间的总体分配
  35. IF OBJECT_ID(‘tb_db_session_space_usage‘ , ‘U‘) IS NOT NULL
  36. DROP TABLE tb_db_session_space_usage
  37. GO
  38. CREATE TABLE tb_db_session_space_usage
  39. (
  40. id INT IDENTITY(1,1) PRIMARY KEY,
  41. session_id INT ,
  42. internal_objects_alloc_page_count INT ,
  43. user_objects_alloc_page_count INT ,
  44. internal_objects_dealloc_page_count INT ,
  45. user_objects_dealloc_page_count INT ,
  46. login_time DATETIME ,
  47. login_name VARCHAR(100) ,
  48. host_name NVARCHAR(128) ,
  49. nt_domain NVARCHAR(128) ,
  50. nt_user_name NVARCHAR(128) ,
  51. program_name NVARCHAR(128) ,
  52. status VARCHAR(50) ,
  53. client_interface_name NVARCHAR(32) ,
  54. cpu_time INT ,
  55. memory_usage INT ,
  56. total_scheduled_time INT ,
  57. total_elapsed_time INT ,
  58. last_request_start_time DATETIME ,
  59. last_request_end_time DATETIME ,
  60. reads INT ,
  61. writes INT ,
  62. logical_reads INT ,
  63. is_user_process BIT ,
  64. row_count BIGINT ,
  65. prev_error INT ,
  66. original_security_id VARBINARY(85) ,
  67. original_login_name NVARCHAR(128) ,
  68. last_successful_logon DATETIME ,
  69. last_unsuccessful_logon DATETIME ,
  70. unsuccessful_logons BIGINT ,
  71. group_id INT
  72. )
  73. GO
  74. -- 4
  75. --  记录正在运行并且做过空间申请的session正在运行的语句.
  76. IF OBJECT_ID(‘tb_db_sql_text‘ , ‘U‘) IS NOT NULL
  77. DROP TABLE tb_db_sql_text
  78. GO
  79. CREATE TABLE tb_db_sql_text
  80. (
  81. id INT IDENTITY(1,1) PRIMARY KEY,
  82. session_id VARCHAR(50) ,
  83. text VARCHAR(MAX),
  84. InDate DATETIME
  85. )
  86. GO
  87. -- 5
  88. --  记录正在运行的活动的空间使用情况以及语句内容和执行计划.
  89. IF OBJECT_ID(‘tb_task_space_usage‘ , ‘U‘) IS NOT NULL
  90. DROP TABLE tb_task_space_usage
  91. GO
  92. CREATE TABLE tb_task_space_usage
  93. (
  94. id INT IDENTITY(1 , 1)PRIMARY KEY ,
  95. session_id INT ,
  96. internal_object_space_MB DECIMAL(18 , 4) ,
  97. internal_object_dealloc_space_MB DECIMAL(18 , 4) ,
  98. text VARCHAR(MAX) ,
  99. statement_text VARCHAR(MAX) ,
  100. query_plan XML
  101. )

http://blog.csdn.net/beirut/article/details/8266203

http://www.cnblogs.com/changbluesky/archive/2010/04/15/1711733.html

tempdb 容量规划:http://msdn.microsoft.com/zh-cn/library/ms345368(SQL.100).aspx

SQL Server中TempDB管理(version store的逻辑结构):http://blogs.msdn.com/b/apgcdsd/archive/2012/03/30/sql-server-tempdb-version-store.aspx

Working with tempdb in SQL Server 2005:http://technet.microsoft.com/zh-cn/library/cc966545

Tempdb怎么会成为性能瓶颈?:http://blogs.msdn.com/b/apgcdsd/archive/2011/01/25/tempdb.aspx

时间: 2024-10-06 18:49:01

[转]如何监测谁用了SQL Server的Tempdb空间的相关文章

sql server转移tempdb数据库的物理存放位置

转移前将原来的文件备份一下 将 tempdb 从其在磁盘上的当前位置移动到其他磁盘位置.由于每次启动 MSSQLSERVER 服务时都会重新创建 tempdb,因此不需要从物理意义上移动数据和日志文件. 1 确定 tempdb 数据库的逻辑文件名称以及在磁盘上的当前位置. SELECT name, physical_name FROM sys.master_files WHERE database_id = DB_ID('tempdb'); GO 2 使用 ALTER DATABASE 更改每个

SQL Server 2008空间数据应用系列一:空间信息基础

转自:http://www.cnblogs.com/beniao/archive/2011/01/18/1933412.html Microsoft SQL Server 2008 提供了全面性的空间支持,可让组织通过具空间功能的应用程序来无缝地取用.使用及扩展以位置为基础的数据,最后可协助用户做出更好的决策.空间分析是一项非常复杂的工作,包含一系列学术内容:地理.数学.天文.图形等.虽然在使用SQL Server 2008的空间特性中不必要深入研究关于地理.数学.天文以及图形等学科,但如果你想

在Windows Server 2012 R2中搭建SQL Server 2012故障转移集群

需要说明的是我们搭建的SQL Server故障转移集群(SQL Server Failover Cluster)是可用性集群,而不是负载均衡集群,其目的是为了保证服务的连续性和可用性,而不是为了提高服务的性能. SQL Server始终在负载均衡集群方面都缺少自己的产品,多由第三方厂家提供,但SQL Server故障转移集群却由来已久,在SQL Server 2012还提供了一个可用性组(AlwaysOn High Availability Groups)的新特性,我们知道微软的故障转移集群(W

SQL Server索引的维护 - 索引碎片、填充因子 &lt;第三篇&gt;

实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题都和页密度有关,虽然两者的表现形式在本质上有所区别,但是故障排除工具是一样的,因为处理是相同的. 对于非常小的表(比64KB小得多),一个区中的页面可能属于多余一个的索引或表---这被称为混合区.如果数据库中有太多的小表,混合区帮助SQL Server节约磁盘空间. 随着表(或索引)增长并且请求超过8个页面,SQL Server创建专用于该表(或索引)的区并且从该区中分配页面.这样一个区被称为统一区,它可以为多达8个相同表或索引的

SQL Server 2008空间数据应用系列八:基于Bing Maps(Silverlight)的空间数据存储

原文:SQL Server 2008空间数据应用系列八:基于Bing Maps(Silverlight)的空间数据存储 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server 2008 R2调测. 2.具备 Transact-SQL 编程经验和使用 SQL Server Management Studio 的经验. 3.具有使用 Microsoft Visual Studio 进行 Microsoft .NET Framework开发的经验. 4.具有

SQL Server安全(11/11):审核(Auditing)

在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切.但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念.这篇文章提供了基础,因此你可以对SQL Server里的安全功能充分利用,不用在面对特定威胁,不能保护你数据的功能上浪费时间. SQL Server审核 SQL Server里的审核指的是你可以在数据库或服务器实例里监控事件.审核日志包含你选择捕获的一系列事件,对于数据库和服务器对象,主体和操作,在服务器上形成活动记录.你可以捕获发生的几乎任

SQL Server 2008空间数据应用系列五:数据表中使用空间数据类型

原文:SQL Server 2008空间数据应用系列五:数据表中使用空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server 2008 R2调测. 2.具备 Transact-SQL 编程经验和使用 SQL Server Management Studio 的经验. 3.熟悉或了解Microsoft SQL Server 2008中的空间数据类型. 4.具备相应(比如OGC)的GIS专业理论知识. 5.其他相关知识. 通过前面几篇文章介绍了

SQL Server 2008空间数据应用系列四:基础空间对象与函数应用

原文:SQL Server 2008空间数据应用系列四:基础空间对象与函数应用 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server 2008 R2调测. 2.具备 Transact-SQL 编程经验和使用 SQL Server Management Studio 的经验. 3.熟悉或了解Microsoft SQL Server 2008中的空间数据类型. 4.具备相应(比如OGC)的GIS专业理论知识. 5.其他相关知识. SQL Server 2

SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础

原文:SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础 在前一篇博文中我们学习到了一些关于地理信息的基础知识,也学习了空间参照系统,既地球椭球体.基准.本初子午线.计量单位.投影等相关理论知识,我们可以使用这些空间参照系统组件来定义一系列应用于地球空间上的几何图像来表示地理空间中的特定功能,表示着地球上一个一个特定的位置点. 本篇主要介绍地理空间索引的概念以及微软SQL Server 2008 R2中的空间索引的应用. 一.空间索引 空间索引是指依据空