2

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

我有一个数据库表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所以我的问题是,为什么在没有空间的情况下选择查询需要很长时间才能执行?我认为,在我的情况下,时间问题与数据量无关。

4

3 回答 3

3

这听起来可能是一个缓存问题。简单来说:

  • 数据存储在硬盘上
  • 当查询进来时,SQL 将数据从硬盘驱动器(磁盘)读取到内存中,然后将其从内存传回给请求它的用户
  • 从磁盘读取数据的时间成本很高
  • 为了提高性能,从磁盘读取到内存的所有数据都会在内存中保留“一段时间”</li>
  • 这样,后续访问相同数据的查询将在内存中找到它,而不必再次从磁盘读取
  • 在 SQL Server 中,这部分内存称为“缓冲区缓存”</li>
  • 在联机丛书(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. 这将返回完全相同的数据集,并且对您的执行时间没有影响。

于 2017-10-27T14:15:57.900 回答
1

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

select * from TblJobs.JobTitle, TblJobs.JobDescription

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

希望这可以帮助。

于 2013-08-01T08:22:33.000 回答
0

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

  1. 查看执行计划寻找线索

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

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

  4. 尝试更改主键的索引类型 - 尝试 Clustered 而不是 Non-Clustered

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

希望你能解决它...

于 2013-08-01T07:57:08.520 回答