2009-07-21 4 views
2

Я решил протестировать nhibernate на существующем приложении (заменив linq на sql), и до сих пор я вижу ужасные результаты. Надеюсь, кто-то здесь может указать мне в правильном направлении.Производительность запросов nhibernate

Мой конфиг:

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> 
    <session-factory> 
     <property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property> 
     <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property> 
     <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property> 
     <property name="connection.connection_string">{my connection string here}</property> 
     <property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property> 
     <property name="adonet.batch_size">10</property> 
     <property name="show_sql">false</property>   
     <property name="use_outer_join">true</property> 
     <property name="command_timeout">60</property> 
     <property name="query.substitutions">false</property>    
    </session-factory> 
</hibernate-configuration> 

Класс домена:

public class Code 
{ 
    public virtual Guid CodeId { get; set; } 
    public virtual string CodeValue { get; set; } 
    public virtual Guid EntryId { get; set; } 
} 

Отображение XML:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SweepstakesWeb" namespace="SweepstakesWeb.Domain"> 
    <class name="Code" table="Codes"> 
     <id name="CodeId"> 
      <generator class="guid.comb"/> 
     </id> 
     <property name="CodeValue" length="20" /> 
     <property name="EntryId" /> 
    </class> 
</hibernate-mapping> 

Когда я запускаю тест, я вижу это:

За нижеследующий запрос:

SELECT this_.CodeId as CodeId0_0_, this_.CodeValue as CodeValue0_0_, this_.EntryId as EntryId0_0_ FROM Codes this_ WHERE this_.CodeValue = N'3734872FVD' 

я получаю:

StmtText 
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
    |--Nested Loops(Inner Join, OUTER REFERENCES:([this_].[CodeID]) OPTIMIZED) 
     |--Index Scan(OBJECT:([Codes].[ix_codes_code] AS [this_]), WHERE:(CONVERT_IMPLICIT(nvarchar(20),[Codes].[CodeValue] as [this_].[CodeValue],0)=N'3734872FVD')) 
     |--Clustered Index Seek(OBJECT:([Codes].[PK__Codes__3493CFA7] AS [this_]), SEEK:([this_].[CodeID]=[Codes].[CodeID] as [this_].[CodeID]) LOOKUP ORDERED FORWARD) 

Если я вручную изменить параметр VARCHAR (удаление префикса N) следующим образом:

SELECT this_.CodeId as CodeId0_0_, this_.CodeValue as CodeValue0_0_, this_.EntryId as EntryId0_0_ FROM Codes this_ WHERE this_.CodeValue = '3734872FVD' 

я получаю:

StmtText 
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
    |--Nested Loops(Inner Join, OUTER REFERENCES:([this_].[CodeID]) OPTIMIZED) 
     |--Index Seek(OBJECT:([Codes].[ix_codes_code] AS [this_]), SEEK:([this_].[CodeValue]='3734872FVD') ORDERED FORWARD) 
     |--Clustered Index Seek(OBJECT:([Codes].[PK__Codes__3493CFA7] AS [this_]), SEEK:([this_].[CodeID]=[Codes].[CodeID] as [this_].[CodeID]) LOOKUP ORDERED FORWARD) 

Обратите внимание, что при значениях параметра varchar instea d nvarchar, я получаю индексный поиск. С nvarchar я получаю сканирование индекса. Тип столбца - varchar (20). По-видимому, происходит неявное преобразование, которое вызывает полное сканирование вместо поиска.

  1. Почему для неявного преобразования требуется сканирование вместо поиска?
  2. Почему nhibernate использует nvarchar по умолчанию, и как я могу сказать ему использовать varchar?

ответ

1

Darn. Через несколько минут после того, как я отправил, я нашел ответ:

http://community.devpinoy.org/blogs/joeycalisay/archive/2007/05/11/nhibernate-unicodes-and-index.aspx

+1

Ссылка уже не действует, и у меня такая же проблема. Можете ли вы дать более полный ответ? –

+0

Если я правильно помню, решение состоит в том, чтобы сделать все ваши столбцы nvarchar. NHibernate автоматически сопоставляет System.String с nvarchar, а при сравнении с varchar он не может использовать поиск индекса. – Chris

+2

Посмотрите эту ссылку для отличного объяснения: http://dylanbeattie.blogspot.com/2010/02/fun-and-games-with-nhibernate-and.html –

Смежные вопросы