从表中获取大量数据时遇到问题。
我有一个数据库表TblJobs
,在此表中某些列包含大量数据(此列中大约有 60,000 个字符)。
我的 table :
TblJobs
JobId JobTitle JobDescription
----------------------------------------------------------------
1 Job1 TextTextTextTextTextTextTextTextTextTextTextText... (approx 40,000 characters without any space in job description)
2 Job2 HelloHelloHelloHelloHelloHelloHelloHelloHelloHell..(approx 60,000 characters without any space in job description)
3 Job3 DemoDemoDemoDemoDemoDemoDemoDemoDemoDemoDemoDemo...(approx 60,000 characters without any space in job description)
4 Job4 TestingTestingTestingTestingTestingTestingTesti....(approx 50,000 characters without any space in job description)
表的结构是:
JobId - Int
JobTitle - VarChar(500)
JobDescription - VarChar(MAX)
现在我的问题是,当我执行查询以从 TblJobs
选择所有列时,执行时间太长(大约 30 秒)。使用这个-
Select * from TblJobs
或
Select JobId, JobTitle, JobDescription from TblJobs
当我将一些数据修改到表的列JobDescription
时,我很惊讶,这个查询只在3-5秒内执行。
在修改中 - 我在 JobDescription
列的数据之间提供了一些空格。
例如,您可以看到下表,其中我仅在 jobDescription
列之间包含一些空格(我没有更改数据类型或数据量):
JobId JobTitle JobDescription
------------------------------------------------------------------------
1 Job1 Text TextTextText**<space>**TextTextTextText**<space>**TextTextTextText... (approx 40,000 characters with some space in job description)
2 Job2 HelloHello**<space>**HelloHelloHelloHello**<space>**HelloHelloHelloHell..(approx 60,000 characters with some space in job description)
3 Job3 DemoDemoDemoDemo**<space>**DemoDemoDemoDemoDemo**<space>**DemoDemoDemo...(approx 60,000 characters with some space in job description)
4 Job4 TestingTesting**<space>**TestingTestingTesting**<space>**TestingTesti....(approx 50,000 characters with some space in job description)
所以我的问题是,当 jobdescription
没有任何空间时,为什么选择查询需要很长时间才能执行?
我认为,时间问题与我的案例中的数据量无关。
最佳答案
这听起来可能是缓存问题。简而言之:
- 数据存储在硬盘上
- 当有查询到来时,SQL 会将数据从硬盘驱动器(磁盘)读取到内存中,然后将其从内存传回给请求它的用户
- 从磁盘读取数据的时间成本很高
- 为了提高性能,从磁盘读取到内存的任何数据都会在内存中保留“一段时间”
- 这样做后,访问相同数据的后续查询将在内存中找到它,而不必再次从磁盘读取
- 在 SQL Server 中,这部分内存称为“缓冲区缓存”
- 在线书籍(SQL Server 文档)和其他地方都有大量关于这一切如何工作的文章和讨论。
所以,我的理论是:
- 当您运行
Select * from TblJobs
时,SQL 将相关数据从磁盘加载到内存 - 当您更新数据时,它首先在内存中更新,然后写回磁盘......更改后的数据保留在内存中
- 当您再次运行
Select * from TblJobs
时,它会直接从内存中读取数据。 - 第一次阅读仍然非常长。正如 @Insac 所说,该表很可能在硬盘驱动器上碎片化,需要“额外”时间来读取。
要对此进行测试,请使用命令DBCC DropCleanBuffers
。这将清除缓冲区高速缓存,要求所有后续查询从磁盘读取。所以:
- 运行
DBCC DropCleanBuffers
以清除缓冲区 - 运行
Select * from TblJobs
直接从磁盘读取数据。计时需要多长时间。 - 再次运行
Select * from TblJobs
,多次,每次计时。这些将从内存中读取 - 运行
DBCC DropCleanBuffers
以再次清除缓冲区 - 运行
Select * from TblJobs
以再次从磁盘读取数据。 - 再次运行
Select * from TblJobs
,多次,每次计时。
很大程度上取决于正在读取的数据量以及计算机上有多少内存 - 但是,嘿,现在内存变得相当大,我怀疑这不会成为问题。
您可以混合运行从 TblJobs 中选择 JobId、JobTitle、JobDescription
。这将返回完全相同的数据集,并且它不会对您的执行时间产生任何影响。
关于sql - 为什么在获取批量数据(没有空间)时SQL查询执行时间过长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17986578/