#c# #asp.net #.net #sql-server #linq-to-sql
#c# #asp.net #.net #sql-сервер #linq-to-sql
Вопрос:
У меня есть программа, которая использует старый Linq для SQL для подключения ASP.NET приложение к базе данных SQL Server. ASP.NET приложение и экземпляр SQL Server находятся на одном компьютере, и обе «среды» обновлены (IIS 10, NET Framework 4.8 и SQL Server 2019).
В программном обеспечении я должен обрабатывать виртуальную корзину с заказом клиента. В корзине много полей, одно из них является nvarchar и содержит «документ корзины», который обычно составляет несколько КБ, но иногда может достигать нескольких МБ (никогда не более 10 МБ)
Когда я удаляю строку документа в диапазоне 2-3 МБ, а затем обновляю одну строку, которая ее содержит, операция udpate выполняется очень, очень медленно (2-2,5 с). Здесь обновите код :
protected void Upsert(CartDto cart, bool isValidationUpsert = false )
{
lock (_sync)
{
if ((cart?.Id ?? 0) <= 0)
throw new ExtendedArgumentException("cartId");
using (var dbContext = ServiceLocator.ConnectionProvider.Instace<CartDataContext>())
{
var repository = new CartRepository(dbContext);
var existingCart = repository.Read(crt => crt.ID == cart.Id).FirstOrDefault();
if (existingCart == null)
{
existingCart = new tbl_set_Cart();
existingCart.Feed(cart);
repository.Create(existingCart);
}
else
{
existingCart.Feed(cart);
repository.Update(existingCart);
}
dbContext.SubmitChanges(); //<<--- This speecifi operation will take 2-2,5s previous instructions take a neglectable time
}
}
}
Я понятия не имею, почему и как повысить производительность в этом сценарии
—ОТРЕДАКТИРОВАНО: как и предлагалось, я профилировал oepration в БД и столкнулся с тем же событием задержки (~ 2,5), если я запускаю код SQL непосредственно на SQL Server (используя SSMS для подключения и выполнения кода).
Здесь код SQL и статистика перфорации :
DECLARE @p0 AS INT = [cart_id];
DECLARE @p1 AS INT = [entry_count];
DECLARE @p2 AS NVARCHAR(MAX) = '..document..';
UPDATE [dbo].[tbl_set_Cart]
SET [ITEMS_COUNT] = @p1, [ITEMS] = @p2
WHERE [ID] = @p0
Вот моя схема таблицы, как вы ничего не видите, это очень просто :
/****** Object: Table [dbo].[tbl_set_Cart] Script Date: 02/12/2021 15:44:07 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl_set_Cart](
[ID] [int] NOT NULL,
[AS400_CUSTOMER_COD] [nvarchar](50) NOT NULL,
[AS400_LISTIN] [int] NOT NULL,
[VALUE] [nvarchar](max) NOT NULL,
[DELIVERY_COSTS] [nvarchar](max) NOT NULL,
[ITEMS_COUNT] [int] NOT NULL,
[ITEMS] [nvarchar](max) NOT NULL,
[KIND] [int] NOT NULL,
[CHECKOUT_INFO] [nvarchar](max) NOT NULL,
[ISSUES] [nvarchar](max) NOT NULL,
[LAST_CHECK] [datetime] NOT NULL,
[USER_ID] [int] NOT NULL,
[IMPERSONATED_USER_ID] [int] NOT NULL,
[OVERRIDE_PRICES] [bit] NOT NULL,
[HAS_ISSUE] [bit] NOT NULL,
[IS_CONFIRMED] [bit] NOT NULL,
[IS_COLLECTED] [bit] NOT NULL,
[_METADATA] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_tbl_set_Cart] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Комментарии:
1. Ни с чем, кроме некоторого кода, нет никаких шансов, что кто-нибудь сможет вам здесь помочь. Но что это за «документ корзины»? Корзина должна состоять не более чем из двух таблиц. CartHeader и cartItems. Я не удивлен, что это может занять пару секунд, если вы перемещаете строки размером 10 МБ через LINQ. Для меня это звучит как проблема с архитектурой.
2. @SeanLange: как я могу быстро передать несколько МБ данных через LinqToSql? Потому что меня удивляет, что это медленно. Я знаю, что это медленно при вставке нескольких записей (выполнение строки одновременно), но почему передача нескольких МБ будет медленной на приличном сервере с SSD-диском, где сеть не задействована?
3. Сравните его, например, с прямым запуском ВСТАВКИ в SqlCommand, чтобы вы знали, насколько виноват L2S
4. Задействована сеть, если только ваше приложение не запущено из того же физического блока, что и ваш sql server, и никто не подключается к этому приложению удаленно. Я все еще говорю, что корзина размером 10 МБ звучит как проблема дизайна, если не приобретаются десятки тысяч уникальных товаров.
5. @CaiusJard: хорошая идея, только что протестировал сгенерированный linq to sql код (простое обновление с текстом) непосредственно в SSMS. Время, затраченное на 2,5 с, как я испытал в приложении. Похоже, что это время, которое потребуется SQL Server для обновления большой строки? как это возможно?
Ответ №1:
После более глубокого изучения профилирования БД с помощью пользователей DBA Stack Overflow (здесь обсуждение https://dba.stackexchange.com/questions/303400/sql-server-how-to-upload-big-json-into-column-performance-issue/303409#303409 ) оказывается, проблема, вероятно, связана с диском.
Поскольку какая-то производственная система столкнулась с той же проблемой, что и моя машина разработки, я спрашиваю, как повысить производительность, и получил прекрасные советы по хранению сжатой версии моих данных. Данные не слишком большие (в моем scanrio), чтобы быть слишком медленными для сжатия / распаковки в памяти во время выполнения, и это значительно сокращает время (используется LZMA). С 2,5 с до ~ 0,3 действительно хорошее улучшение.
Спасибо всем за ценную помощь и советы.