与simplerepository相比,使用activerecord的亚音速linq非常慢

时间:2010-01-15 00:35:51

标签: subsonic performance

当使用活动记录与simplerepository查询时,任何人都知道为什么linq查询的速度大约慢6倍? 以下代码运行速度比使用简单存储库查询数据时慢6倍。此代码在循环中执行1000次

提前致谢

        string ret = "";            
//      if (plan == null)
        {
           plan =VOUCHER_PLAN.SingleOrDefault(x => x.TENDER_TYPE == tenderType);
        }
        if (plan == null)
           throw new InvalidOperationException("voucher type does not exist." + tenderType);

        seq = plan.VOUCHER_SEQUENCES.First();
        int i = seq.CURRENT_NUMBER;
        seq.CURRENT_NUMBER += seq.STEP;
        seq.Save();

3 个答案:

答案 0 :(得分:2)

我们对此进行了一些分析,发现SubSonic的记录.SingleOrDefault(x => x.id = someval)比通过CodingHorror完成的同一查询慢20倍。在此处记录:https://github.com/subsonic/SubSonic-3.0/issues/258

分析器在ExecutionBuilder.cs中指出了这一点:

// this sucks, but since we don't track true SQL types through the query, and ADO throws exception if you
// call the wrong accessor, the best we can do is call GetValue and Convert.ChangeType
Expression value = Expression.Convert(
    Expression.Call(typeof (Convert), "ChangeType", null,
                    Expression.Call(reader, "GetValue", null, Expression.Constant(iOrdinal)),
                    Expression.Constant(TypeHelper.GetNonNullableType(column.Type), typeof(Type))
        ),
    column.Type
    );

令人失望,因为我非常喜欢SubSonic / Linq。

最后我们放弃了,我写了这个 - http://www.toptensoftware.com/petapoco。移植后,我们的负载测试显示每秒请求数增加,CPU负载从大约80%下降到5%。

答案 1 :(得分:0)

通过在构造函数/ init过程中缓存它创建的数据库实例,我能够在性能上产生巨大的差异。我现在看到的是加速2-3倍,取决于情况和运行。

1)如果只调用默认构造函数,只需用静态实例替换_db的方法就可以正常工作,并具有相同的速度优势。

// MyProject.MyDB _db;
// replace with a static instance, and remove the "this." from other lines
static MyProject.MyDB _db = new MyDB();

public MyClass() {
    //_db=new MyProject.MyDB();
    Init();
}

2)我为数据库条目编写了一个小缓存类,并在使用“new()”的所有旧位置从我的ActiveRecord.tt文件中调用它。

// REPLACE "MyDB" with the name of your DB.  Alternately, include this 
// class in Context.tt and have it generate the correct name.  

class ContextDatabaseCache {        

    public static MyDB GetMyDB()
    {
        return GetInstance("~~default~~", () => new MyDB());
    }

    public static MyDB GetMyDB(string connectionString) {
        return GetInstance(connectionString, () => new MyDB(connectionString));
    }

    public static MyDB GetMyDB(string connectionString, string providerName)
    {
        return GetInstance(connectionString + providerName, () => new MyDB(connectionString, providerName));
    }

    private static Dictionary<string, MyDB> _dict = new Dictionary<string, MyDB>();
    private static MyDB GetInstance(string key, Func<MyDB> createInstance)
    {
        if (!_dict.ContainsKey(key)) {               
            lock (_dict) {
                if (!_dict.ContainsKey(key)) {
                    _dict.Add(key, createInstance());
                }
            }
        }
        return _dict[key];
    }

    ///<summary>Call this when the "DefaultConnection" string changes in the
    ///         App.exe.config file so that a new db instance will be created
    ///         and pick up the changed value. </summary>
    public static void Clear() {
         _dict.Clear();
    }

}

这是在ActiveRecord.tt文件中进行的替换类型:

public <#=tbl.ClassName#>(){
    _db=new <#=Namespace#>.<#=DatabaseName#>DB();
    Init();            
}

    // becomes this: 
public <#=tbl.ClassName#>(){
    _db= <#=Namespace#>.ContextDatabaseCache.Get<#=DatabaseName#>DB();
    Init();            
}

答案 2 :(得分:0)

显然这对于​​亚音速来说“不是问题”,尽管他们知道它存在。它不会被修复。你必须使用一个糟糕的批处理查询语法来获得这个,没有人会这样做。

我不明白的是,这是90%的情况。从表中获取记录列表。它应该 BE 是快速的,而不是慢的。无论何时何地,每个人都会这样做。

亚音速问题很多。我不得不为DB field =&gt;编写缓存对象字段查找,因为它们也非常缓慢。