Мы выполняем своего рода репликацию по собственной инициативе из базы данных SQL Server 2008 R2 в базу данных MySQL 5.1. Это неверная репликация, поскольку блок MySQL действует как постоянное хранилище, а SQL Server - это то, что мы вынуждены использовать в качестве агрегатора данных.
Итак, я написал хранимую процедуру, которая проверяет последнюю строку, вставленную в мою таблицу, о которой идет речь, в базе данных MySQL, заполняет временную таблицу на конце SQL Server новой партией строк для вставки обратно в блок MySQL. и делает вставки. Проблема в том, что это мучительно медленно. У меня есть отставание> 24 миллионов строк для отправки из коробки SQL Server в MySQL, и со скоростью, с которой я получаю <2 строки в секунду, для завершения потребуется почти 6 месяцев, и я никогда не смогу быть в курсе с новыми данными при попадании в базу данных SQL Server. </p>
Ящики не находятся в одной и той же сети - ящик MySQL стоит чертовски близко к подключению страны к магистрали Интернета, но ящик SQL Server (по независящим от нас причинам) подключен только через линию бизнес-DSL ( не позитив скорости восходящего потока). Если я подключаюсь через командную строку (в отличие от запросов через связанный сервер в SQL Server), я могу вставлять строки в базу данных MySQL в среднем ~ 0,03 секунды на строку. Это наводит меня на мысль, что либо моя хранимая процедура просто невероятно неэффективна, либо OPENQUERY / Linked Servers по своей сути просто медленны. Вот хранимая процедура:
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
Я знаю, что это грязно ... мы пробовали разные подходы, чтобы заставить это работать, так что, вероятно, есть неиспользуемые переменные и т. Д. Для чего стоит просто выполнить первый запрос на выборку на связанном сервере, что потребует вверх 40 секунд.
РЕДАКТИРОВАТЬ: Вот мои настройки сервера:
- Провайдер:
Microsoft OLE Provider for ODBC Drivers
- Наименование продукта:
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 Out:
FALSE
- Использовать дистанционную сортировку:
TRUE
- Имя сопоставления:
(Blank)
- Время ожидания соединения:
0
- Тайм-аут запроса:
0
- Дистрибьютор:
FALSE
- Издатель:
FALSE
- Подписчик:
FALSE
- Ленивая проверка схемы:
FALSE
- Включить продвижение распределенных транзакций:
TRUE