0

我有一个C#应用程序,它基本上为测试数据库生成大量数据。它使用的是Oracle.DataAccess版本4.112.3.0

出于某种奇怪的原因,每 30 次插入 OracleCommand.ExecuteNonQuery() 语句将持续秒钟。在某些情况下,我们正在谈论15 秒!

通过 DSN 使用通用 ODBC 连接时,我没有遇到此问题。我无法返回使用 DSN,因为我希望此应用程序即使在没有安装 oracle 客户端的系统上也能正常工作。

非常感谢任何帮助

我的连接类的代码,处理打开连接并执行插入 - 设置适用于 SQLServer 和 Oracle

public Connection(string username,
            string password,
            string serverAddress,
            String servicename,
            string qual)
        {
            uid = username;
            pwd = password;
            server = serverAddress;
            oraServiceName = servicename;
            qualifier = qual;
            string oradb = "Data Source=(DESCRIPTION="
                             + "(ADDRESS=(PROTOCOL=TCP)(HOST=" + serverAddress + ")(PORT=1521))"
                             + "(CONNECT_DATA=(SERVICE_NAME="+servicename+")));"
                             + "User Id=" + username + ";Password=" + password + ";";
                oraConn = new OracleConnection(oradb);
                oraCom = new OracleCommand("",oraConn);
                oraCom.CommandType = System.Data.CommandType.Text;


        } 
public void doInsert(string s)
        {

            try
            {
                sqlCom.CommandText = s;
                sqlCom.Connection = sqlConn;
                sqlCom.ExecuteNonQuery();
            }
            catch (NullReferenceException e)
            {
                try
                {
                    oraCom.CommandText = s;
                   // oraCom.Connection = oraConn;

                    oraCom.ExecuteNonQuery();

                }
                catch (NullReferenceException e2)
                {
                    throw e2;
                }
            }

        }

实际插入的代码

public void generateData()
    {
        try
        {
            indivID = GenerateId();
            conn.openConn();
            conn.doInsert(tData.insertIndividual());
            //number of calls
            for (long x = 0; x < numCalls; x++)
            {
                countCalls++;
                callidkey = GenerateId();

                //start segments
                for (long y = 0; y < numSegments; y++)
                {
                    if (countSegs != numSegments)
                    {
                        countSegs++;
                    }
                    else
                    {
                        countSegs = 0;
                    }
                    INTX_ID = GenerateId();
                    conn.doInsert(this.tData.insertINTXSEGMENT());
                    //start parts and recordings
                    for (long n = 0; n < numParts; n++)
                    {

                       // INTX_PART_ID = GenerateId();
                        conn.doInsert(tData.insertINTXPART());
                        if (countParts != numParts)
                        {
                            countParts++;
                        }
                        else
                        {
                            countParts = 0;
                        }
                        if (genRec)
                        {

                            recData.recordingid = GenerateId();
                            conn.doInsert(recData.insertRecData());
                            conn.doInsert(recData.insertRecPart());
                            if (countRecs != numParts)
                            {
                                countRecs++;
                            }
                            else
                            {
                                countRecs = 0;
                            }
                        }
                    }
                }
            }
        }
        catch (Exception)
        {}
        }
    }
4

1 回答 1

1

我不是程序员,只是一个dba。有几件事要记住:

  1. 尽可能重用打开的连接 - 连接管理需要很长时间。
  2. 为您的插入使用绑定变量,最好使用批量收集。

如果你实现了这 2 个简单的规则,接下来要检查的是数据库在线重做日志文件的大小。默认为 512KB。如果它们已满,您的应用程序将冻结,直到下一个重做文件中有空间。重做以循环方式使用。如果数据库处于归档日志模式,则当它们被填满时,它们将被复制到归档中。这可能会导致在执行许多插入时速度变慢。

检查数据库的日志模式:

select log_mode from v$database;

检查重做大小和组数:

select group#, bytes, first_time from v$log;

重做应该在非常快的存储上。它只是在做顺序 io。如果重做与正常负载相比较小,则增加它们的大小。(通常我们的目标是每 15 分钟进行一次日志切换)如果您不断有更多,请增加大小。如果通常你在一小时内有大约 4 个开关,并且只有你的负载很快就会填满它们,那么添加日志组。

于 2012-05-10T15:02:41.013 回答