У меня есть хранимая процедура SQL CLR, которая анализирует строку TLVBER, эта процедура CLR вызывается каждый раз, когда команда отправляется в БД, имеется 6 команд.Выполнение хранимых процедур CLR из SQL Server
Команды 6 представляют собой одну транзакцию.
В каждой команде принимают строку TLVBER, я разбираю строку в тегах с их значением, затем вставляю ее или обновляю в соответствующем столбце/таблице. Важно, чтобы этот тег существовал в БД, я проверяю его с помощью запроса.
Чтобы узнать, в какой колонке/таблице тег вставлен или обновлен, у меня есть таблица в БД, где я храню id_tag
, таблицу и столбец.
Вот проблема:
Я не знаю, что это лучший вариант, чтобы сделать, потому что я закодирован весь процесс в CLR, я сделал много запросов и вставляет & обновления.
Одна единственная проблема, например, заключается в том, что я должен создать временную таблицу, и я прочитал, что это не рекомендуется, поэтому я решаю это с помощью CLR, потому что вы можете использовать ArrayList; в общем, проще с кодом C#, чем с T-SQL.
С другой стороны I've мысль вставить все теги в одной таблице, и ссылки эти метки с идентификатором, потому что если я хранить все теги в одном столе, я буду хранить теги все разные КОМАНДЫ, отправленные в базу данных.
Это критическое время обработки, поскольку в минуту будет совершаться тысячи транзакций.
В CLR мне приходится запрашивать данные из БД (могут ли запросы скомпрометировать время, необходимое для CLR?).
Следующая проблема заключается в конце разбора TLVBER, поскольку мне нужно объединить результаты анализа и сравнить каждый тег (каждый тег итерации его с помощью ArrayList) разобрать и запросить таблицу/столбец, где вставлен или обновлен. Я думал, что было бы лучше построить запросы, вернуть его как таблицу в T-SQL, чтобы выполнение было быстрее в T-SQL, чем в CLR.
В любом случае мне нужно сделать много запросов к БД для получения информации, так есть способ отправить таблицы в CLR SP ?; чтобы избежать запросов из CLR, вместо этого было бы лучше запросить необходимые данные в T-SQL и отправить его в CLR, чтобы этот процесс обрабатывал данные и не вступал в какое-либо взаимодействие с БД (без соединений, которые генерируют задержки, только обработка данных).
Ну код ниже покажет вам, как я призываю CLR от T-SQL, то я покажу вам петлю, где я делаю запросы и вставляет & обновления
EXEC SP_CLR_PARSEATLVBER @TLV= '00102001010010010100100201007F010101',
@[email protected] OUTPUT,
@CMD='OPN'
while (cursor <= total)
{
Stag = "";
// -- * ******************EXTRAE TAG*******************
tag = TLV.ToString().ToCharArray(cursor, 4);
foreach (char c in tag)
Stag = Stag + c;
Stag = "0x" + Stag;
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" '" + "TAG:" + Stag + "'," +
" '128'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
SeleccionaTag.CommandText = "SELECT id_tag FROM dbo.tags where dbo.tags.id_tag = '" + Stag + "'";
SeleccionaTag.Connection = conn;
reader = SeleccionaTag.ExecuteReader();
int vacio = 0;
String id_tag = "";
while (reader.Read())
{
vacio++;
id_tag = reader.GetSqlString(0).ToString();
}
reader.Close();
if (vacio == 0)
{
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'ID_TAG NO SE ENCUENTRA'," +
" '137'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
}
{
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" '" + "Vacio:" + id_tag + "'," +
" '137'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
}
//-- /////////////////////////////////////
// --*******************AVANCE EN LA CADENA*******************
cursor = cursor + 4;
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'Cursor despues de extraer tag(" + Stag + "): " + cursor.ToString() + "'," +
" '137'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
// -- /////////////////////////////////////
// --*******************EXTRAE TAMAÑO EN BYTES DEL TAG EXTRAIDO *******************
length = TLV.ToString().ToCharArray(cursor, 2);
Slength = "";
foreach (char c in length)
Slength = Slength + c;
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'TAMAÑO DE TAG:" + Slength + "'," +
" '209'," +
" SYSDATETIME()" +
")";
Int32.TryParse(Slength, NumberStyles.HexNumber,
new CultureInfo("en-US"), out varlength);
InsertaLog.ExecuteNonQuery();
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'TAMAÑO DE TAG(INT):" + varlength.ToString() + "'," +
" '218'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
Slength = "";
if ((varlength) > 127)
{
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
"'TAG SUPERA LONGITUD'," +
" '227'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
varlength = 0;
// --*******************AVANCE EN LA CADENA*******************
cursor = cursor + 2;
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'Cursor despues de extraer tamaño de TAG(" + tag + "):" +cursor+ "'," +
" '237'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
// -- /////////////////////////////////////
TotalBytes = varlength - 128;
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'Total de Bytes Asignados de la longitud del TAG(" + tag + "):" + TotalBytes+"',"+
" '246'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
length = TLV.ToString().ToCharArray(cursor, 2);
foreach (char c in length)
Slength = Slength + c;
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'TAMAÑO DE TAG:" + Slength + "'," +
" '257'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
Int32.TryParse(Slength, NumberStyles.HexNumber,
new CultureInfo("en-US"), out varlength);
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'TAMAÑO DE TAG(INT):" + varlength.ToString() + "'," +
" '266'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
varlength = varlength * 2;
//--*******************AVANCE EN LA CADENA*******************
cursor = cursor + (TotalBytes * 2);
// -- /////////////////////////////////////
}
else
{
length = TLV.ToString().ToCharArray(cursor, 2);
Slength = "";
foreach (char c in length)
Slength = Slength + c;
Int32.TryParse(Slength, NumberStyles.HexNumber,
new CultureInfo("en-US"), out varlength);
//--*******************AVANCE EN LA CADENA*******************
cursor = cursor + 2;
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'Slength:" + Slength + "'," +
" '286'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'TAMAÑO DE TAG(INT):" + varlength.ToString() + "'," +
" '294'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
// -- /////////////////////////////////////
}
//-- /////////////////////////////////////
//-- * ******************EXTRAE VALOR DE TAG EXTRAIDO *******************
value = TLV.ToString().ToCharArray(cursor, varlength);
foreach (char c in value)
Svalue = Svalue + c;
SeleccionaTipoDato.CommandText = "SELECT dbo.TAGS.tipodato" +
" FROM dbo.TAGS" +
" WHERE dbo.TAGS.id_tag = '" + tag + "'";
SeleccionaTipoDato.Connection = conn;
reader = SeleccionaTipoDato.ExecuteReader();
while (reader.Read())
{
tipoDato = reader.GetSqlString(0).ToString();
}
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'TipoDato:" + tipoDato.ToString() + "'," +
" '294'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
reader.Close();
if (tipoDato.Equals("ASCII"))
{
Convertidor C = new Convertidor();
valorParseadoASCII=C.ValueToASCII(Svalue);
}
cursor = cursor + varlength;
//-- /////////////////////////////////////
//-- ******************* Tabla para agregar tags con su respectivo valor *******************
Tupla.Add(Stag);
Tupla.Add(Svalue);
if(tag.Equals("0x2005"))
TID = Svalue;
if(tag.Equals("0x1003"))
MID = Svalue;
if (tag.Equals("0xE001"))
xid = Convert.ToInt64(Svalue);
CMD.Add(Tupla);
InsertaLog.CommandText = "INSERT INTO DBO.LOGDB values " +
" ('PARSEATLVBER', " +
" 'Tupla Agregada: (" + Tupla[0]+","+Tupla[1] + ")'," +
" '320'," +
" SYSDATETIME()" +
")";
InsertaLog.ExecuteNonQuery();
Tupla.Clear();
Svalue = "";
Slength = "";
Stag = "";
//-- /////////////////////////////////////
}
// INSERCION DE CAMPO LLAVE
if (cmd.Equals("OPN"))
{
SeleccionaNuevaLLave.CommandText = "SELECT NEXT VALUE FOR dbo.llave";
reader = SeleccionaNuevaLLave.ExecuteReader();
while (reader.Read())
SecuenciaLlave = Convert.ToInt64(reader.GetSqlString(0));
reader = SeleccionaNuevaLLave.ExecuteReader();
SeleccionaNuevaTransId.CommandText = "SELECT NEXT VALUE FOR dbo.transid";
while (reader.Read())
SecuenciaTransid = Convert.ToInt64(reader.GetSqlString(0));
InsertaNuevaTransaccion.CommandText = "INSERT INTO dbo.transaccion"+
" values (xid,trans_id,mid,tid)" +
" ("+SecuenciaLlave + "," +
SecuenciaTransid + "," +
MID + "," +
TID +
")";
InsertaNuevaTransaccion.CommandText = "INSERT INTO DBO.AMT (xid) values (" + SecuenciaLlave +")"; InsertaNuevaTransaccion.ExecuteNonQuery();
InsertaNuevaTransaccion.CommandText = "INSERT INTO DBO.CRD (xid) values (" + SecuenciaLlave + ")"; InsertaNuevaTransaccion.ExecuteNonQuery();
InsertaNuevaTransaccion.CommandText = "INSERT INTO DBO.DMO (xid) values (" + SecuenciaLlave + ")"; InsertaNuevaTransaccion.ExecuteNonQuery();
InsertaNuevaTransaccion.CommandText = "INSERT INTO DBO.HST (xid) values (" + SecuenciaLlave + ")"; InsertaNuevaTransaccion.ExecuteNonQuery();
InsertaNuevaTransaccion.CommandText = "INSERT INTO DBO.MRC (xid) values (" + SecuenciaLlave + ")"; InsertaNuevaTransaccion.ExecuteNonQuery();
InsertaNuevaTransaccion.CommandText = "INSERT INTO DBO.PRO (xid) values (" + SecuenciaLlave + ")"; InsertaNuevaTransaccion.ExecuteNonQuery();
InsertaNuevaTransaccion.CommandText = "INSERT INTO DBO.RCV (xid) values (" + SecuenciaLlave + ")"; InsertaNuevaTransaccion.ExecuteNonQuery();
InsertaNuevaTransaccion.CommandText = "INSERT INTO DBO.SND (xid) values (" + SecuenciaLlave + ")"; InsertaNuevaTransaccion.ExecuteNonQuery();
}
else
{
SecuenciaLlave = xid;
}
int j = 0;
String tabla,columna;
foreach (ArrayList A in CMD)
{
SeleccionaTipoDato.CommandText = "SELECT dbo.TAGS.tabla,"+
" dbo.TAGS.columna" +
" FROM dbo.TAGS" +
" WHERE dbo.TAGS.id_tag = '" + A[0].ToString() + "'";
reader = SeleccionaTipoDato.ExecuteReader();
while (reader.Read())
{
tabla = reader.GetSqlString(0).ToString();
columna = reader.GetSqlString(1).ToString();
ActualizaTabla.CommandText = "UPDATE "
+tabla+
" SET "
+columna+"='"+A[1]+"'"+
" where "+tabla+".xid="+SecuenciaLlave;
ActualizaTabla.ExecuteNonQuery();
}
}
Игнорируйте вставки в DBO. LOGDB, они предназначены для целей отладки, другие запросов & Вставка и обновления являются критическим процессом.
Вопрос в том, как я могу выполнять обработку данных в CLR, передавая их таблицы и анализируя данные, а только строить запросы и отправлять их в T-SQL, чтобы это выполнялось ?, или нет никаких проблем при задержке вызова запросов & вставки & обновления.
Считайте, что эта процедура CLR будет называться много, много раз в минуту.
CLR использует память за пределами установленного предела настроек памяти, поэтому я рекомендую проверить запрос на тестовом сервере с максимальным входом и увидеть CLR-память. Производительность clr может быть проверена путем просмотра использования памяти компонентов clr через (выберите * из sys.dm_os_memory_clerks, где type = 'memoryclerk_clr'.Чтобы передать datatables в clr, создайте тип таблицы, определенный пользователем, в sql – TheGameiswar
. Другое дело, что использование CLR означает, что запрос будет выполняться последовательно. См. http: // blogs .technet.com/b/italian_premier_center_for_sql_server/archive/2013/09/04/sqlclr-functions-and-parallelelism.aspx. Если возможно, инкапсулируйте логику в функцию (возможно, clr), которая не нуждается в доступе к данным, и выполните rest в T-SQL. –
@TheGameiswar re «Чтобы передать данные в clr, создайте определенный тип таблицы в sql»: это, к сожалению, неправда. Объекты SQLCLR не могут принимать TVP. Если вы хотите передать в таблицу, вы можете либо передать строку с разделителями, которая будет разбираться (например, строка запроса HTTP), либо вы можете хранить данные в локальной временной таблице и передавать имя этой таблицы, а из нее - SELECT в объекте SQLCLR. –