2013-06-12 50 views
0

我们在ASP Web应用程序中使用nHibernate和session-per-request模式。用户能够执行的某些操作会导致数百条INSERT和UPDATE语句,这些语句需要几秒钟才能完成。这会导致性能不佳,因为用户在整个事务提交到数据库之前无法查看其操作结果。长时间提交会导致nHibernate性能下降

顺便说一句,以前我们将结果保存在会话中,但这也不是一个好的解决方案。将内容写入会话会导致读写锁定,因此并发请求将按顺序处理。长请求会阻止其他请求直到完成。这就是为什么我们将结果写入数据库的原因,但正如我所解释的那样,这带有一系列问题。

我们如何解决这个问题?我只能想到将结果bakc发送到浏览器,同时在后台提交结果。如果可能的话,我不知道会话是如何与浏览器的请求耦合的。但也许这是可能的?或者有解决方案可行吗?

编辑

  • 我们使用Guid.Comb标识符战略
  • 给的大小的想法提交:单个提交涉及超过2000 INSERT和UPDATE语句,并在运行过程中的操作发出类似数量的SELECT语句。提交需要2-4分钟才能完成(那么长?)。

请问我没有提供足够的信息。我不知道现在在这里写什么会很有趣,因为我不知道我应该在哪个方向寻找解决方案。

回答

0

您尚未发布任何代码,但在大多数情况下,您可以在NHibernate中使用批处理获得更好的性能。设置较大的批量大小将导致数据库的往返次数减少。但是你可能不得不重写一些代码。

<property name="adonet.batch_size">1000</property> 

将配置您的批量大小。

第二种选择是使用IStatelessSession而不是ISession。你没有任何状态,只是表现可以提高。

+0

设置BATCHSIZE大型也会影响检索性能消极我认为。在这种情况下,无状态会话不是一种选择,因为这意味着我们失去了大部分INSERT和UPDATE语句的级联。 – Pieter

3

我写的这个问题就在这里:

http://www.philliphaydon.com/2011/09/the-benefits-of-letting-the-orm-generate-the-identity-part-1/

如果您使用的是在数据库中生成IDENTITYGUID S,你会从缓慢插入受苦,无法批。

当使用GUID插入到SQL中时,NHibernate首先发出请求以获取新的GUID。

您与交易结束了,像这样:

- statement #1 
begin transaction with isolation level: Unspecified 

- statement #2 
select newid() 

- statement #3 
select newid() 

- statement #4 
select newid() 

- statement #5 
INSERT INTO Fruit 
      (Name, 
      Id) 
VALUES  ('Apple0' /* @p0_0 */, 
      '269bc638-74b4-4568-85d1-45b6e537fcbd' /* @p1_0 */) 

INSERT INTO Fruit 
      (Name, 
      Id) 
VALUES  ('Apple1' /* @p0_1 */, 
      'fc848779-b173-4c31-b8b6-0a7735c0c2dc' /* @p1_1 */) 

INSERT INTO Fruit 
      (Name, 
      Id) 
VALUES  ('Apple2' /* @p0_2 */, 
      '232c8971-18c7-486d-9152-26c969c3b632' /* @p1_2 */) 

- statement #6 
commit transaction 

同样,当您使用的身份,NHibernate的需要选择新的ID背出数据库中的更新模型,这是特别重要的,当NHibernate的需求在插入前将这个新对象与另一个对象联系起来

使用IDENTITY结束了与交易看起来像:

- statement #1 
begin transaction with isolation level: Unspecified 

- statement #2 
INSERT INTO People 
      (FirstName, 
      Surname) 
VALUES  ('Phillip0' /* @p0 */, 
      'Haydon' /* @p1 */); 

select SCOPE_IDENTITY() 

- statement #3 
INSERT INTO People 
      (FirstName, 
      Surname) 
VALUES  ('Phillip1' /* @p0 */, 
      'Haydon' /* @p1 */); 

select SCOPE_IDENTITY() 

- statement #4 
INSERT INTO People 
      (FirstName, 
      Surname) 
VALUES  ('Phillip2' /* @p0 */, 
      'Haydon' /* @p1 */); 

select SCOPE_IDENTITY() 

- statement #5 
commit transaction 

一个相当不错的计算机上运行一些基本的测试我插结果与下面的时序:

  • IDENTITY 28951ms
  • NEWID 30241ms

将此更新为使用HiLo或G uidComb允许NHibernate自己生成身份。

使用HiLo,NHibernate会发出一个下一个hi值的请求,然后更新hi值,一旦有hi就可以生成一系列的Ids,直到lo满了。

这导致插入像这样:

- statement #1 
begin transaction with isolation level: Unspecified 

- statement #2 
Reading high value: 
select next_hi 
from hibernate_unique_key with (updlock, rowlock) 

- statement #3 
Updating high value: 
update hibernate_unique_key 
set next_hi = 3 /* @p0 */ 
where next_hi = 2 /* @p1 */ 

- statement #4 
INSERT INTO People 
      (FirstName, 
      Surname, 
      Id) 
VALUES  ('Phillip0' /* @p0_0 */, 
      'Haydon' /* @p1_0 */, 
      202 /* @p2_0 */) 

INSERT INTO People 
      (FirstName, 
      Surname, 
      Id) 
VALUES  ('Phillip1' /* @p0_1 */, 
      'Haydon' /* @p1_1 */, 
      203 /* @p2_1 */) 

INSERT INTO People 
      (FirstName, 
      Surname, 
      Id) 
VALUES  ('Phillip2' /* @p0_2 */, 
      'Haydon' /* @p1_2 */, 
      204 /* @p2_2 */) 

- statement #5 
commit transaction 

同样使用GuidComb,NHibernate的会生成一个GUID为您:

- statement #1 
begin transaction with isolation level: Unspecified 

- statement #2 
INSERT INTO Fruit 
      (Name, 
      Id) 
VALUES  ('Apple0' /* @p0_0 */, 
      'db902160-edbb-49c7-bf52-9f660018299a' /* @p1_0 */) 

INSERT INTO Fruit 
      (Name, 
      Id) 
VALUES  ('Apple1' /* @p0_1 */, 
      '5e852528-3a6f-41d2-a6b1-9f660018299a' /* @p1_1 */) 

INSERT INTO Fruit 
      (Name, 
      Id) 
VALUES  ('Apple2' /* @p0_2 */, 
      '2f63c6e8-e595-4393-ad15-9f660018299a' /* @p1_2 */) 

- statement #3 
commit transaction 

这意味着NHibernate的不需要往返数据库在执行插入操作时,这两个操作都允许发生批量插入操作,就像您在HiLo和GuidComb中看到的那样,只有一条语句被发送到服务器,而不像NEWID/IDENTITY那样为每个插入语句发送语句,每个新的ID都被制成。

这导致像低得多的时间:

  • 希洛9287ms
  • GuidComb 9060ms

我希望帮助:)

+0

我们已经在使用GuidComb,所以这不是我们可以改进的地方。 – Pieter

相关问题