如何提高ADO.NET中大规模INSERT的速度?

发布于 2024-10-11 03:15:17 字数 10635 浏览 3 评论 0原文

我下载了高级数据库服务器 (ADS) 10.1 的试用版,以及 ARC 和 ADO.NET 提供程序。我的主要目的是了解与 SQLite .NET (http://sqlite.phxsoftware.com/) 相比,从数百万条记录中进行大规模插入的性能。

在 ADS 中,30 分钟内加载了 700 万条条目。

在 Sqlite for.NET 中,同样的 700 万个条目在不到 3 分钟内就被加载了!

为什么?我可以采取哪些措施来提高 .NET 提供商的 ADS 速度?

问候 。

编辑

感谢您的建议,在ADS代码中我错误地包含了一些索引的创建,当我抑制它时,加载经过的时间是10分钟。

让我添加一些示例代码和示例数据(您可以将其相乘,直到获得 700 万个条目)。如果您能找到增强和优化性能的方法,请告诉我。

SYBASE ADS 代码:

 public void LoadAds(string opt, string file)
    {
        AdsConnection conn = new AdsConnection(@"data source=C:\apps\dataApps\cmpExistenc\inv.ads;" +
            "ServerType=local; TableType=ADT");
        conn.Open();
        var stV = new st();
        var dicTxt = new Dictionary<object, st>();
        if (opt.ToUpper() == "C")
        {
            using (AdsCommand cmd = conn.CreateCommand())
            {
                try
                {
                    cmd.CommandText = "DROP TABLE lbl; DROP TABLE almlbl";
                    cmd.ExecuteNonQuery();
                }
                catch { }
                cmd.CommandText =
                    "CREATE TABLE lbl (alm varchar(4), alm2 varchar(4), " +
                       "mat varchar(18), ser varchar(20), fac varchar(18), almlbl varchar(10), " +
                       "cant integer, sts varchar(1), ser_2_20 varchar(20), rowid_sap integer, stsmat varchar(100));";
                cmd.ExecuteNonQuery();
                cmd.CommandText =
                    "CREATE TABLE almlbl (almlbl varchar(10), almlbltxt varchar(100), " +
                       "ciudad varchar(50));";
                cmd.ExecuteNonQuery();
            }
        }
        else
            using (AdsCommand cmdTxt = conn.CreateCommand())
            {
                cmdTxt.CommandText = "SELECT * from almlbl";
                AdsDataReader drT = cmdTxt.ExecuteReader();
                while (drT.Read())
                    dicTxt[drT[0]] = new st() { almlblTxt = drT[1], ciudad = drT[2] };
                drT.Dispose();
                cmdTxt.CommandText = "DELETE FROM almlbl";
                cmdTxt.ExecuteNonQuery();
            }


        using (AdsTransaction transac = conn.BeginTransaction())
        {
            AdsCommand cmd = conn.CreateCommand();
            cmd.Transaction = transac;
            AdsParameter param = cmd.CreateParameter();
            cmd = LibCorp.Ads.buildParmsFromTable("lbl", conn, transac);
            long regLei = 0;
            List<object> cols;
            try
            {
                StreamReader sr = new StreamReader(file, Encoding.Default);
                sr.ReadLine(); // Ignore title
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    if ((++regLei % 1000000) == 0)
                        o.show(string.Format(" lbl:{0}", regLei), tbx);
                    cols = new List<object>(line.Split('|'));
                    if (!dicTxt.ContainsKey((string)cols[5]))
                    {
                        stV.almlblTxt = cols[6];
                        stV.ciudad = cols[8];
                        dicTxt[cols[5]] = stV;
                    }
                    if (!cols[3].Equals("") && cols[3].ToString().Length > 18)
                        cols.Add(cols[3].ToString().Substring(1));
                    else
                        cols.Add(DBNull.Value);

                    cmd.Parameters[0].Value = cols[0];       // alm
                    cmd.Parameters[1].Value = cols[1];       // alm2
                    cmd.Parameters[2].Value = cols[2];       // mat
                    cmd.Parameters[3].Value = cols[3];       // ser
                    cmd.Parameters[4].Value = cols[4];       // fac
                    cmd.Parameters[5].Value = cols[5];       // almlbl
                    cmd.Parameters[6].Value = cols[7];       // cant
                    cmd.Parameters[7].Value = DBNull.Value;  // sts
                    cmd.Parameters[8].Value = cols[10];      // ser_2_20
                    cmd.Parameters[9].Value = DBNull.Value;  // rowid_sap
                    cmd.Parameters[10].Value = cols[9];      // stsmat
                    cmd.ExecuteNonQuery();
                }

                foreach (KeyValuePair<object, st> pair in dicTxt)
                {
                    cmd.CommandText = string.Format("INSERT INTO almlbl VALUES('{0}','{1}','{2}')",
                            pair.Key, pair.Value.almlblTxt, pair.Value.ciudad);
                    cmd.ExecuteNonQuery();
                }

                transac.Commit();
            }
            catch (Exception ex)
            {
                o.notify(string.Format("{0}\n\rSitio->{1}", ex, ex.TargetSite.Name));
            }
            finally
            {
                conn.Close();
            }

        }
    }

.NET SQLite 代码:

public void LoadSQLITE(string opt, string file)
    {
        conn = new SQLiteConnection
            (@"Data Source=inv.db3; Page Size=65536; Cache Size=65536; Synchronous=Off; Journal Mode=Off;");
        conn.Open();
        var stV = new st();
        var dicTxt = new Dictionary<object, st>(); // faster than SortedDictionary
        if (opt.ToUpper() == "C")
        {
            using (SQLiteCommand cmd = new SQLiteCommand(conn))
            {
                try
                {
                    cmd.CommandText = "DROP TABLE lbl; DROP TABLE almlbl";
                    cmd.ExecuteNonQuery();
                }
                catch { }
                cmd.CommandText =
                    "CREATE TABLE lbl (alm varchar(4), alm2 varchar(4), " +
                       "mat varchar(18), ser varchar(20), fac varchar(18), almlbl varchar(10), " +
                       "cant integer, sts varchar(1), ser_2_20 varchar(20), rowid_sap integer, stsmat varchar);" +
                    "CREATE TABLE almlbl (almlbl varchar(10), almlbltxt varchar(100), " +
                       "ciudad varchar(50));"; //+
                cmd.ExecuteNonQuery();
            }
        }
        else
            using (SQLiteCommand cmdTxt = new SQLiteCommand(conn))
            {
                cmdTxt.CommandText = "SELECT * from almlbl";
                SQLiteDataReader drT = cmdTxt.ExecuteReader();
                while (drT.Read())
                    dicTxt[drT[0]] = new st() { almlblTxt = drT[1], ciudad = drT[2] };
                drT.Dispose();
                cmdTxt.CommandText = "DELETE FROM almlbl";
                cmdTxt.ExecuteNonQuery();
            }

        using (SQLiteTransaction transac = conn.BeginTransaction())
        {
            using (SQLiteCommand cmd = new SQLiteCommand(conn))
            {
                SQLiteParameter param = new SQLiteParameter();
                SQLiteCommand cmdAux = LibCorp.Lite.buildParmsFromTable("lbl", conn);
                cmd.CommandText = cmdAux.CommandText;
                foreach (SQLiteParameter sp in cmdAux.Parameters)
                    cmd.Parameters.Add(sp);
                long regLei = 0;
                try
                {
                    StreamReader sr = new StreamReader(file, Encoding.Default);
                    sr.ReadLine(); // Ignore title
                    List<object> cols;
                    string line;
                    while (!string.Equals(line = sr.ReadLine(), null)) // Fastest way
                    {
                        if ((++regLei % 1000000) == 0)  //Diff of only 1 or 2 secs if omitted
                            o.show(string.Format(" lbl:{0}", regLei), tbx);
                        cols = new List<object>(line.Split('|')); // Fastest way
                        if (!dicTxt.ContainsKey((string)cols[5])) // diff of only 1 sec if commented
                        {
                            stV.almlblTxt = cols[6];
                            stV.ciudad = cols[8];
                            dicTxt[cols[5]] = stV;
                        }

                        if (!cols[3].Equals("") && cols[3].ToString().Length > 18)
                            cols.Add(cols[3].ToString().Substring(1));
                        else
                            cols.Add(DBNull.Value);

                        cmd.Parameters[0].Value = cols[0];       // alm
                        cmd.Parameters[1].Value = cols[1];       // alm2
                        cmd.Parameters[2].Value = cols[2];       // mat
                        cmd.Parameters[3].Value = cols[3];       // ser
                        cmd.Parameters[4].Value = cols[4];       // fac
                        cmd.Parameters[5].Value = cols[5];       // almlbl
                        cmd.Parameters[6].Value = cols[7];       // cant
                        cmd.Parameters[7].Value = DBNull.Value;  // sts
                        cmd.Parameters[8].Value = cols[10];      // ser_2_20
                        cmd.Parameters[9].Value = DBNull.Value;  // rowid_sap
                        cmd.Parameters[10].Value = cols[9];      // stsmat
                        cmd.ExecuteNonQuery();
                    }

                    foreach (KeyValuePair<object, st> pair in dicTxt)
                    {
                        cmd.CommandText = string.Format("INSERT INTO almlbl VALUES('{0}','{1}','{2}')",
                                pair.Key, pair.Value.almlblTxt, pair.Value.ciudad);
                        cmd.ExecuteNonQuery();
                    }

                    transac.Commit();
                }
                catch (Exception ex)
                {
                    o.notify(string.Format("{0}\n\rSitio->{1}", ex, ex.TargetSite.Name));
                }
                finally
                {
                    conn.Close();
                }
            }

        }
    }

以及一些测试数据(乘以 700 万,请包括标题行):

COD_ALMACEN_SAP|COD_ALMACEN_SAP2|CODIGO_SAP|NRO_SERIE_INICIAL|NRO_INICIO_FACTURA|COD_ALMACEN|NOMBRE_ALMACEN|CANTIDAD|CIUDAD|NOMBRE_ARTICULO

1030|8030|ADAJKIUSD66K|||16|ALMACEN DANSA PRUZ TESULARES|4|BANDA PRUZ|ADA -KI-SD66K 适配器 MAIDIUM SD-66K 1030|8030|BAT-KI-BPA101|||16|阿尔马森兰塔克鲁斯特苏拉雷斯|5|班达普鲁兹|BAT-KI-BPA101 电池 1020|8020|TARGESA/P_PC-GC79|||17|周边中心|9|POCHASALTA|TARGESA/P_PC-GC79 TARGESA 通用 P PC GPRS Y WL 1010|8010|TARJETA/P_PC-GC79|||1014|领土北 1|5|PATPAZ|TARGESA/P_PC-GC79 TARJETA 通用 P PC GPRS Y WL 1060|8060|TARJETA/P_PC-GC79|||1095|ALMACEN SUNY|1|TRONOSAD|TARGESA/P_PC-GC79 TARGESA 通用 P PC GPRS Y WL

enter code here

问候。

问候。

I downloaded a trial of Advanced Database Server (ADS) 10.1, together with ARC and ADO.NET provider. My main intention was to know the performance of massive INSERTS from millions of records compared to SQLite .NET (http://sqlite.phxsoftware.com/).

In ADS, 7 millions entries were loaded in 30 minutes.

In Sqlite for.NET, the same 7 millions entries were loaded in less than 3 minutes!!

Why? What can I do to enhance the speed in ADS with the .NET provider?

Regards .

EDIT

Thanks for your recommendations, In ADS code I mistakenly included the creation of some indexes, when I suppressed this, the loading elapsed time was 10 minutes.

Let me add some example code and sample data (which you can multiply until getting 7 million entries). If you can find ways to enhance and optimize performance, please let me know.

CODE FOR SYBASE ADS:

 public void LoadAds(string opt, string file)
    {
        AdsConnection conn = new AdsConnection(@"data source=C:\apps\dataApps\cmpExistenc\inv.ads;" +
            "ServerType=local; TableType=ADT");
        conn.Open();
        var stV = new st();
        var dicTxt = new Dictionary<object, st>();
        if (opt.ToUpper() == "C")
        {
            using (AdsCommand cmd = conn.CreateCommand())
            {
                try
                {
                    cmd.CommandText = "DROP TABLE lbl; DROP TABLE almlbl";
                    cmd.ExecuteNonQuery();
                }
                catch { }
                cmd.CommandText =
                    "CREATE TABLE lbl (alm varchar(4), alm2 varchar(4), " +
                       "mat varchar(18), ser varchar(20), fac varchar(18), almlbl varchar(10), " +
                       "cant integer, sts varchar(1), ser_2_20 varchar(20), rowid_sap integer, stsmat varchar(100));";
                cmd.ExecuteNonQuery();
                cmd.CommandText =
                    "CREATE TABLE almlbl (almlbl varchar(10), almlbltxt varchar(100), " +
                       "ciudad varchar(50));";
                cmd.ExecuteNonQuery();
            }
        }
        else
            using (AdsCommand cmdTxt = conn.CreateCommand())
            {
                cmdTxt.CommandText = "SELECT * from almlbl";
                AdsDataReader drT = cmdTxt.ExecuteReader();
                while (drT.Read())
                    dicTxt[drT[0]] = new st() { almlblTxt = drT[1], ciudad = drT[2] };
                drT.Dispose();
                cmdTxt.CommandText = "DELETE FROM almlbl";
                cmdTxt.ExecuteNonQuery();
            }


        using (AdsTransaction transac = conn.BeginTransaction())
        {
            AdsCommand cmd = conn.CreateCommand();
            cmd.Transaction = transac;
            AdsParameter param = cmd.CreateParameter();
            cmd = LibCorp.Ads.buildParmsFromTable("lbl", conn, transac);
            long regLei = 0;
            List<object> cols;
            try
            {
                StreamReader sr = new StreamReader(file, Encoding.Default);
                sr.ReadLine(); // Ignore title
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    if ((++regLei % 1000000) == 0)
                        o.show(string.Format(" lbl:{0}", regLei), tbx);
                    cols = new List<object>(line.Split('|'));
                    if (!dicTxt.ContainsKey((string)cols[5]))
                    {
                        stV.almlblTxt = cols[6];
                        stV.ciudad = cols[8];
                        dicTxt[cols[5]] = stV;
                    }
                    if (!cols[3].Equals("") && cols[3].ToString().Length > 18)
                        cols.Add(cols[3].ToString().Substring(1));
                    else
                        cols.Add(DBNull.Value);

                    cmd.Parameters[0].Value = cols[0];       // alm
                    cmd.Parameters[1].Value = cols[1];       // alm2
                    cmd.Parameters[2].Value = cols[2];       // mat
                    cmd.Parameters[3].Value = cols[3];       // ser
                    cmd.Parameters[4].Value = cols[4];       // fac
                    cmd.Parameters[5].Value = cols[5];       // almlbl
                    cmd.Parameters[6].Value = cols[7];       // cant
                    cmd.Parameters[7].Value = DBNull.Value;  // sts
                    cmd.Parameters[8].Value = cols[10];      // ser_2_20
                    cmd.Parameters[9].Value = DBNull.Value;  // rowid_sap
                    cmd.Parameters[10].Value = cols[9];      // stsmat
                    cmd.ExecuteNonQuery();
                }

                foreach (KeyValuePair<object, st> pair in dicTxt)
                {
                    cmd.CommandText = string.Format("INSERT INTO almlbl VALUES('{0}','{1}','{2}')",
                            pair.Key, pair.Value.almlblTxt, pair.Value.ciudad);
                    cmd.ExecuteNonQuery();
                }

                transac.Commit();
            }
            catch (Exception ex)
            {
                o.notify(string.Format("{0}\n\rSitio->{1}", ex, ex.TargetSite.Name));
            }
            finally
            {
                conn.Close();
            }

        }
    }

CODE FOR SQLITE FOR .NET:

public void LoadSQLITE(string opt, string file)
    {
        conn = new SQLiteConnection
            (@"Data Source=inv.db3; Page Size=65536; Cache Size=65536; Synchronous=Off; Journal Mode=Off;");
        conn.Open();
        var stV = new st();
        var dicTxt = new Dictionary<object, st>(); // faster than SortedDictionary
        if (opt.ToUpper() == "C")
        {
            using (SQLiteCommand cmd = new SQLiteCommand(conn))
            {
                try
                {
                    cmd.CommandText = "DROP TABLE lbl; DROP TABLE almlbl";
                    cmd.ExecuteNonQuery();
                }
                catch { }
                cmd.CommandText =
                    "CREATE TABLE lbl (alm varchar(4), alm2 varchar(4), " +
                       "mat varchar(18), ser varchar(20), fac varchar(18), almlbl varchar(10), " +
                       "cant integer, sts varchar(1), ser_2_20 varchar(20), rowid_sap integer, stsmat varchar);" +
                    "CREATE TABLE almlbl (almlbl varchar(10), almlbltxt varchar(100), " +
                       "ciudad varchar(50));"; //+
                cmd.ExecuteNonQuery();
            }
        }
        else
            using (SQLiteCommand cmdTxt = new SQLiteCommand(conn))
            {
                cmdTxt.CommandText = "SELECT * from almlbl";
                SQLiteDataReader drT = cmdTxt.ExecuteReader();
                while (drT.Read())
                    dicTxt[drT[0]] = new st() { almlblTxt = drT[1], ciudad = drT[2] };
                drT.Dispose();
                cmdTxt.CommandText = "DELETE FROM almlbl";
                cmdTxt.ExecuteNonQuery();
            }

        using (SQLiteTransaction transac = conn.BeginTransaction())
        {
            using (SQLiteCommand cmd = new SQLiteCommand(conn))
            {
                SQLiteParameter param = new SQLiteParameter();
                SQLiteCommand cmdAux = LibCorp.Lite.buildParmsFromTable("lbl", conn);
                cmd.CommandText = cmdAux.CommandText;
                foreach (SQLiteParameter sp in cmdAux.Parameters)
                    cmd.Parameters.Add(sp);
                long regLei = 0;
                try
                {
                    StreamReader sr = new StreamReader(file, Encoding.Default);
                    sr.ReadLine(); // Ignore title
                    List<object> cols;
                    string line;
                    while (!string.Equals(line = sr.ReadLine(), null)) // Fastest way
                    {
                        if ((++regLei % 1000000) == 0)  //Diff of only 1 or 2 secs if omitted
                            o.show(string.Format(" lbl:{0}", regLei), tbx);
                        cols = new List<object>(line.Split('|')); // Fastest way
                        if (!dicTxt.ContainsKey((string)cols[5])) // diff of only 1 sec if commented
                        {
                            stV.almlblTxt = cols[6];
                            stV.ciudad = cols[8];
                            dicTxt[cols[5]] = stV;
                        }

                        if (!cols[3].Equals("") && cols[3].ToString().Length > 18)
                            cols.Add(cols[3].ToString().Substring(1));
                        else
                            cols.Add(DBNull.Value);

                        cmd.Parameters[0].Value = cols[0];       // alm
                        cmd.Parameters[1].Value = cols[1];       // alm2
                        cmd.Parameters[2].Value = cols[2];       // mat
                        cmd.Parameters[3].Value = cols[3];       // ser
                        cmd.Parameters[4].Value = cols[4];       // fac
                        cmd.Parameters[5].Value = cols[5];       // almlbl
                        cmd.Parameters[6].Value = cols[7];       // cant
                        cmd.Parameters[7].Value = DBNull.Value;  // sts
                        cmd.Parameters[8].Value = cols[10];      // ser_2_20
                        cmd.Parameters[9].Value = DBNull.Value;  // rowid_sap
                        cmd.Parameters[10].Value = cols[9];      // stsmat
                        cmd.ExecuteNonQuery();
                    }

                    foreach (KeyValuePair<object, st> pair in dicTxt)
                    {
                        cmd.CommandText = string.Format("INSERT INTO almlbl VALUES('{0}','{1}','{2}')",
                                pair.Key, pair.Value.almlblTxt, pair.Value.ciudad);
                        cmd.ExecuteNonQuery();
                    }

                    transac.Commit();
                }
                catch (Exception ex)
                {
                    o.notify(string.Format("{0}\n\rSitio->{1}", ex, ex.TargetSite.Name));
                }
                finally
                {
                    conn.Close();
                }
            }

        }
    }

AND SOME DATA FOR TESTING (MULTIPLY UNTIL 7 MILLIONS, PLEASE INCLUDE TITLE LINE):

COD_ALMACEN_SAP|COD_ALMACEN_SAP2|CODIGO_SAP|NRO_SERIE_INICIAL|NRO_INICIO_FACTURA|COD_ALMACEN|NOMBRE_ALMACEN|CANTIDAD|CIUDAD|NOMBRE_ARTICULO

1030|8030|ADAJKIUSD66K|||16|ALMACEN DANSA PRUZ TESULARES|4|BANDA PRUZ|ADA-KI-SD66K ADAPTADOR MAIDIUM SD-66K
1030|8030|BAT-KI-BPA101|||16|ALMACEN LANTA CRUZ TESULARES|5|BANDA PRUZ|BAT-KI-BPA101 BATERIESAPS
1020|8020|TARGESA/P_PC-GC79|||17|PERRITORIAL CENTER|9|POCHASALTA|TARGESA/P_PC-GC79 TARGESA UNIVERSAL P PC GPRS Y WL
1010|8010|TARJETA/P_PC-GC79|||1014|TERRITORIES NORTH 1|5|PATPAZ|TARGESA/P_PC-GC79 TARJETA UNIVERSAL P PC GPRS Y WL
1060|8060|TARJETA/P_PC-GC79|||1095|ALMACEN SUNY|1|TRONOSAD|TARGESA/P_PC-GC79 TARGESA UNIVERSAL P PC GPRS Y WL

enter code here

Regards.

Regards.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

死开点丶别碍眼 2024-10-18 03:15:17

首先确保在这两种情况下您使用的事务和查询是相同的。第二,确保您以相同的方式调用插入查询 - 不要在一种情况下创建冗余(对于每个插入调用)连接、查询或适配器对象,而在另一种情况下则不然。差别太……显着了。

First of all ensure, that in both cases you are using transaction and query is the same. 2nd ensure, that you're calling the Insert query in the same way - do not create redundant (for every Insert call) connection, query or adapter object in one case but not in other. The difference is too ... significant.

零崎曲识 2024-10-18 03:15:17

尝试删除交易。 ADS 事务与传统的 RDBMS 不同,需要更多的操作系统刷新操作(ADS 不使用检查点)。如果没有事务,性能会更好。

编辑注意到您正在使用本地服务器,因此我对交易的评论将不相关。当当!

另外,我不知道第二个循环(INSERT INTO almlbl)涉及多少个循环,但更改为带有参数的准备好的查询会有所帮助。

所有这些 SQLite 行很可能尚未位于磁盘上。我假设有相当多的内容在内存中并且还没有被刷新。

Try removing the transaction. ADS transactions are different than traditional RDBMS and require more OS flush operations (ADS doesn't use checkpoints). Performance will be way better without the transaction.

Edit Noticed you are using local server, so my comments about the transaction will not be relevant. Dang!

Also, I don't know how many loops are involved in the second loop (INSERT INTO almlbl), but changing to a prepared query with params would help.

It's fairly likely that all of those SQLite rows are not on disk yet. I would assume quite a few are in memory and haven't been flushed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文