mysql - 从 SQL Server 到 MySQL 链接服务器的缓慢 INSERT

标签 mysql sql-server replication linked-server

我们正在进行一种从 SQL Server 2008 R2 数据库到 MySQL 5.1 数据库的自行复制。这不是真正的复制,因为 MySQL 框充当永久存储,而 SQL Server 是我们被迫用作数据聚合器的东西。

因此,我编写了一个存储过程,用于检查在 MySQL 数据库中插入到我的相关表中的最新行,在 SQL Server 端填充一个临时表,并用一批新行插入回 MySQL 框, 并插入。问题是,这太慢了。我有超过 2400 万行的积压要从 SQL Server 框发送到 MySQL,并且以我得到 <2 行/秒的速度,将需要将近 6 个月才能完成并且永远无法跟上在新数据到达 SQL Server 数据库时使用新数据。

这些盒子不在同一个网络上——MySQL 盒子非常靠近国家与互联网主干网的连接,但 SQL Server 盒子(出于我们无法控制的原因)仅通过商业 DSL 线路连接(对上游速度不利)。如果我通过命令行连接(而不是通过 SQL Server 中的链接服务器进行查询),我能够以平均每行约 0.03 秒的速度在 MySQL 数据库中插入行。这让我相信要么我的存储过程效率低得令人难以置信,要么 OPENQUERY/链接服务器本身就很慢。这是存储过程:

DECLARE @LastSensorLogDateFormatted DATETIME
DECLARE @LastSensorLogDate VARCHAR(30)
DECLARE @LastSensorLogMillis INT
DECLARE @LastSensorLogEibaddress VARCHAR(30)
DECLARE @SensorLogReplicated BIGINT
DECLARE @counter INT

-- Create a temporary table to store last write 
-- to MySQL database on CASALA-DB01
CREATE TABLE #SensorLogRecord 
  (LastSensorLogDate VARCHAR(30)
  , LastSensorLogMillis INT
  , LastSensorLogEibaddress VARCHAR(30))            

-- Dump result of query on CASALA-DB01 into our temporary table
INSERT INTO #SensorLogRecord
  (LastSensorLogDate, LastSensorLogMillis, LastSensorLogEibaddress )
  (SELECT  date, date_millis, eib_address
  FROM 
    OPENQUERY(MYSQL4, 'SELECT date, date_millis, eib_address 
    FROM cabie.sensors_log_redux ORDER BY date desc LIMIT 1'))

-- Store the last sensor log date and EIB address 
-- from our temporary table into local vars
SELECT 
  @LastSensorLogDate = LastSensorLogDate, 
  @LastSensorLogMillis = LastSensorLogMillis, 
  @LastSensorLogEibaddress = LastSensorLogEibaddress 
FROM #SensorLogRecord

SET @LastSensorLogDateFormatted = 
    CAST((LEFT(@LastSensorLogDate, 20) + 
    CAST(@LastSensorLogMillis as VARCHAR)) AS DATETIME)

SET @counter = 0            
WHILE (1=1)
  BEGIN
    CREATE TABLE #RecordHolder (Id BIGINT)

    INSERT INTO #RecordHolder (Id)
      SELECT TOP 1000 Sensor_Id FROM dbo.Sensors_Log
      WHERE Sensor_Id NOT IN (SELECT * FROM dbo.Sensors_Archivals)
      AND dbo.Sensors_Log.Date <= GETDATE()
      AND dbo.Sensors_Log.EibAddress <> @LastSensorLogEibaddress
      AND dbo.Sensors_Log.Date <> @LastSensorLogDateFormatted

  INSERT OPENQUERY(MYSQL4, 
    'SELECT date, eib_address, ip_address, value, application, phys_address 
    FROM sensors_log_redux_holding')        
  SELECT 
    CONVERT(VARCHAR, GNH.dbo.Sensors_Log.Date,121),
    GNH.dbo.Sensors_Log.EibAddress,
    GNH.dbo.Sensors_Log.Ip_Address,
    GNH.dbo.Sensors_Log.Value,
    GNH.dbo.Sensors_Log.Application,
    GNH.dbo.Sensors_Log.Phys_Address 
  FROM GNH.dbo.Sensors_Log 
  JOIN #RecordHolder  
    ON (#RecordHolder.Id = GNH.dbo.Sensors_Log.Sensor_Id)

  INSERT INTO dbo.Sensors_Archivals (Row_Id) SELECT Id FROM #RecordHolder

  DROP TABLE #RecordHolder  

  IF (@counter >= 1000000)
   BREAK
END

我知道这很麻烦......我们一直在尝试不同的方法来让它工作,所以可能有未使用的变量等。就其值(value)而言,仅在链接服务器上运行第一个选择查询需要向上40 秒。

编辑:这是我的链接服务器设置:

  • 提供程序:用于 ODBC 驱动程序的 Microsoft OLE 提供程序
  • 产品名称:MySQL 5.1
  • 提供程序字符串:DRIVER={MySQL ODBC 5.1 Driver};SERVER=192.168.17.5;DATABASE=cabie;USERNAME=ourUsername;PASSWORD=ourPassword
  • 高级选项:
    • 排序规则兼容:FALSE
    • 数据访问:TRUE
    • RPC:FALSE
    • RPC 输出:FALSE
    • 使用远程整理:TRUE
    • 排序规则名称:(空白)
    • 连接超时:0
    • 查询超时:0
    • 经销商:FALSE
    • 发布者:FALSE
    • 订阅者:FALSE
    • 惰性架构验证:FALSE
    • 启用分布式事务的推广:TRUE

最佳答案

这是问题的一部分......

# Provider:用于 ODBC 驱动程序的 Microsoft OLE Provider
# Provider String: DRIVER={MySQL ODBC 5.1 Driver};...

ODBC 是出了名的慢,您在两端 都使用它。

另一种方法是用 Delphi 或 C(#) 编写应用程序。 如果此应用程序使用 native 客户端 dll 连接到数据库。

我知道带有开源 ZEOS 数据库的 Delphi 使用可从 Microsoft 和 MySQL 免费获得的客户端 dll,传输数据的速度将比 ODBC 快很多倍。

C# 或任何使用本地客户端 dll 和 SQL 的现代编程语言也可以完成这项工作。 确保如果您使用中间程序在两个数据库之间建立桥接,它不会回退到 ODBC,许多(主要是较旧的)编程环境出于懒惰或廉价而使用与您获得的相同糟糕的传输速度现在。

希望这有助于...

关于mysql - 从 SQL Server 到 MySQL 链接服务器的缓慢 INSERT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5014740/

相关文章:

mysql - distinct or group?哪个在mysql中效率更高?

mysql - Sqlite3 创建表时出错

asp.net - 无法在具有 Docker 支持和 Visual Studio 提供的 SQL Server 的 Visual Studio 中进行本地调试

sql-server - 合并复制 - 触发器在发布者和订阅者上触发

mongodb - mongo : ERROR: child process failed, 退出,错误号 100

java - mySQL 中的 ID 值是 auto_increment 但似乎是在 netbeans 中生成的

mysql - 当它是mysql中另一个表中的主键时如何更改外键的数据类型

sql-server - 是否可以编写查询来查找没有 JOIN 和 ORDER BY 的最大记录?

c# - 将大型 xml 文件插入 xml 列的最佳方法(在远程 SQL Server 上)

sql-server - 在还原 SQL Server 数据库之前等待连接关闭