使用Management Studio,我在SQL Server上有一个包含以下六列的表:
FileID - int
File_GUID - nvarchar(258)
File_Parent_GUID - nvarchar (258)
File Extension nvarchar(50)
File Name nvarchar(100)
File Path nvarchar(400)
它在FileID上有一个主键。
此表有大约200M行。 如果我尝试处理完整数据,则会收到内存错误。 所以我决定在分区中加载它,每隔20M使用一个select语句,我在文件ID号上拆分。
这些选择需要永远,行的检索速度非常慢,我不知道为什么......没有任何计算,只需使用SELECT提取数据。
当我运行查询分析器时,我看到:
Select cost = 0%
Clustered Index Cost = 100%
你们是否知道为什么会发生这种情况或者我可以提出一些技巧?
我的查询: 选择* FROM Dim_TFS_File
谢谢!
答案 0 :(得分:0)
在查询运行时监控查询是否被阻止或等待资源。如果您无法在监控数据库和客户端计算机时轻松查看瓶颈,我建议您运行几个简单的测试,以帮助确定您应该集中精力的地方。理想情况下,运行测试时没有其他重要活动和冷缓存。
首先,在数据库服务器上运行查询并丢弃结果。这可以通过SSMS使用丢弃结果选项(查询 - >查询选项 - >结果 - >网格 - >执行后丢弃结果)来完成。或者,使用类似下面的Powershell脚本:
$connectionString = "Data Source=YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI;Application Name=Performance Test";
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString);
$command = New-Object System.Data.SqlClient.SqlCommand("SELECT * FROM Dim_TFS_File;", $connection);
$command.CommandTimeout = 0;
$sw = [System.Diagnostics.Stopwatch]::StartNew();
$connection.Open();
[void]$command.ExecuteNonQuery(); #this will discard returned results
$connection.Close();
$sw.Stop();
Write-Host "Done. Elapsed time is $($sw.Elapsed.ToString())";
在客户端计算机上重复上述测试。经过的时间差反映了数据传输网络开销。如果客户端计算机测试明显快于应用程序,请将精力集中在应用程序代码上。否则,请仔细查看数据库和网络。以下是一些可能有助于解决性能问题的随机说明。
这个简单的查询可能会执行完整的聚簇索引扫描。数据库服务器上的限制性能因素是:
CPU:此单线程查询的吞吐量将受到单CPU核心的限制。
存储:SQL Server存储引擎将在大型扫描期间使用预读取来异步获取数据,以便在查询需要时数据已经存储在内存中。顺序读取性能对于跟上查询非常重要。
碎片:碎片将导致更多磁盘头移动到旋转介质,每个物理磁盘IO增加几毫秒。这通常只考虑单主轴或低端本地存储阵列上的大型顺序扫描,而不是SSD或企业级SAN。通过重组或重建聚簇索引可以消除碎片。请务必指定MAXDOP 1进行重建以获得最大收益。
SQL Server流的结果与客户端应用程序可以使用的结果一样快,但客户端可能会受到网络带宽和延迟的限制。看来你要返回许多GB的数据,这需要相当长的时间。您可以使用不同的数据类型大幅减少带宽需求。例如,假设GUID命名列实际上包含GUID,使用uniqueidentifier而不是nvarchar将在netowrk和磁盘上每行节省大约80个字节。同样,如果您实际上不需要使用Unicode字符将数据大小减半,请使用varchar而不是nvarchar。
客户端处理时间:应用程序代码处理20M行的时间将受到CPU和代码效率(尤其是内存管理)的限制。由于内存不足,您似乎要么将所有行加载到内存中,要么发生泄漏。即使没有彻底的内存不足错误,高内存使用也会导致分页并大大降低吞吐量。重要的是,如果应用程序代码无法像返回数据那样快速地处理行,那么数据库和网络性能就没有实际意义。