为什么SQL查询在获取批量数据(无空间)时执行时间太长?

时间:2013-08-01 06:24:16

标签: sql database sql-server-2008

从表中获取大量数据时遇到问题。

我有一个数据库表TblJobs,在此表中,某些列包含大量数据(此列中约有60,000个字符)。

我的表:

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没有任何空间时,为什么选择查询需要花费太长时间才能执行? 我认为,时间问题与我案例中的数据量无关。

3 个答案:

答案 0 :(得分:0)

我真的不知道它为什么喜欢这个,但你可能想尝试一些事情:

  1. 查看执行计划以找到线索

  2. 将*替换为实际的列名称 - 不知道原因,但有时会有所帮助

  3. 为每列添加索引并尝试(直到找到最佳列)

  4. 尝试更改主键的索引类型 - 尝试群集而不是非群集

  5. 尝试在此表上创建一个视图,并从视图中查询

  6. 希望你能解决它......

答案 1 :(得分:0)

从表中选择*总是会相当慢,因为您要求DBMS扫描整个表中的每一行并返回结果。如果您想要特定结果并进行优化,我建议您修改查询以选择所需的特定列。 例如

select * from TblJobs.JobTitle, TblJobs.JobDescription

至于您的工作描述中的文本之间的空间导致更快的检索时间,这更多的是猜测,但可能是由于您或DBMS在设置表时指定的索引性质?极长的连续字符串可能需要更长时间才能读取或确定从何处继续检索数据。那个或DBMS有缓存机制,可能在第一次执行后使第二次搜索更快(参见here

希望这有帮助。

答案 2 :(得分:0)

这听起来像是一个缓存问题。简而言之:

  • 数据存储在硬盘上
  • 当查询进入时,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几次,每次计时。

在很大程度上取决于正在读取的数据量和机器上的内存量 - 但是,嘿,这些天内存变得非常大,我怀疑这不会是一个问题。

您可以混合使用Select JobId, JobTitle, JobDescription from TblJobs。这将返回完全相同的数据集,并且它对您的执行时间没有任何影响。