我正在开展一个由其他人完成的大项目。这段代码里面有很多项目,它使用NHibernate作为ORM。数据库非常繁忙,所以我试图诊断它缓慢的地方并尝试诊断整个系统流程。
我所做的其中一件事是为NHibernate.SQL添加一个log4net,它将所有正在运行的查询输出到日志文件中:
<logger name="NHibernate.SQL" additivity="false">
<level value="ALL" />
<appender-ref ref="NHibernateSQLAppender" />
</logger>
这是appender:
<appender name="NHibernateSQLAppender" type="log4net.Appender.RollingFileAppender">
<file value="NHibernateSQL.txt"></file>
<appendToFile value="true"></appendToFile>
<maximumFileSize value="15MB"></maximumFileSize>
<maxSizeRollBackups value="10"></maxSizeRollBackups>
<rollingStyle value="Size"></rollingStyle>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] [%line] %-5p %c [%x] <%X{auth}> - %m%n"></param>
</layout>
</appender>
在日志文件中,我看到一个在短时间内运行多次的查询,我想找到运行它的代码。我能够通过表名找到hbm文件,以及它映射到的类。
我搜索了该类的引用 - 但有很多。
所以我的基本问题是如何找到运行该特定查询的代码?甚至可能吗?
由于
答案 0 :(得分:1)
您是否尝试过Nhibernate Profiler?使用分析器将有所帮助,如果我记得正确,我认为你得到每个查询的堆栈跟踪?
的更多信息答案 1 :(得分:0)
您可以在&lt; logger&gt;中设置名称(空格)。仅限NHibernate(没有.SQL),这将非常冗长。然后,您可以从ALL返回TRACE或DEBUG级别,或查找包含有用信息的特定命名空间。
你的应用程序也使用log4net吗?然后,您可以获取应用程序和NHibernate的组合日志,检查发送查询的内容。只需添加另一个&lt; logger /&gt;阻止您的应用程序的命名空间;你可以使用相同的&lt; appender&gt;!
通常,您可以在SQL查询中轻松查看数据库对象。
多次(通常是100次)相同的查询指出了臭名昭着的N + 1问题 - 通过遍历父项并初始化子集合来为多个父对象/行加载下级行/对象。例如,发送
SELECT * FROM Children WHERE ParentId=@parid /* for some 100 Parent objects. */
这是之前返回N个父对象的第一个(1)查询,以及每个父对象上的子集合的N个查询。
当程序员不熟悉NHibernate集合并实现错误时,N + 1甚至会变得更糟,或者在没有NHibernate集合映射的情况下开始编写自己的集合处理(将NHibernate理解为OR Mapper,从SQL结果中创建对象或者oherwise)。通过连接替换可能会导致过大的结果集(笛卡尔积)。但NHibernate也是数据库访问的优化器,在会话工厂配置( adonet.batch_size 50,例如)中提供N + 1和怪物连接之间的良好方式,即批量设置,然后在每个类元素和集合属性上设置 batch-size 。