Загрузка ЦП становится высокой, когда только 20 пользователей одновременно вставляют данные отслеживания в географическую таблицу - PullRequest
0 голосов
/ 12 мая 2019

У нас есть приложение для отслеживания в реальном времени, в которое мы вставляем точку отслеживания в одну таблицу с именем Tracking.У нас есть еще одна таблица с именем ExistingAddressPointTable, где у нас есть адрес доставки.Мы рассматриваем конкретный адрес как доставленный, когда доставщик находится в радиусе 200 метров от этого адреса, и вставляем запись доставки в непространственную таблицу, называемую таблицей Delivery (отношения многие ко многим).

Мы создаем APIзвоните через 20-30 секунд каждой минуты, следовательно, устройство всегда отправляет 10-15 адресных точек в этот период.Я реализую решение для этого в хранимой процедуре, но проблема заключается даже в том, что сеанс одновременной доставки 20 человек в Azure SQL Server достигает 100%.Я хочу поддерживать эту систему для 1000 одновременных сеансов.

Мы используем базу данных Azure SQL Server в эластичном пуле, имеющем ограничение 50 DTU в среде UAT.У нашего клиента уже есть 5 других БД по 250 ГБ каждый в том же эластичном пуле.Для производства также у нас есть ограничение в 100 DTU.

Любое решение для достижения Delivery Мальчик отслеживает через разные мобильные устройства?

Используемая технология: ядро ​​.net, Web API и Azure SQL Server 2017, пространственная индексация в пространственной таблице (Tracking & ExistingAddressPointTable) уже применяется.Любая помощь очень ценится.

PSB код для справки

CREATE Procedure [dbo].[InsertTrackingPoint]
    @points AddressPointType READONLY,
    @name NVARCHAR(150),
    @isDisConnected BIT,
    @jobId BIGINT     -- with current scenario of implementation.This is not required
AS 
BEGIN
Declare @routeId bigint;
Declare @point nvarchar(700);
DECLARE @totalRecords INT
DECLARE @I INT
DECLARE @trackingId bigint
Declare @deliveryBoyId bigint;
DECLARE @route As TABLE(Id int Identity,RouteId bigint,JobId bigint);
Select Top 1 @deliveryBoyId=Id from DeliveryPerson with(Nolock) where --Take DeliveryPerson Id FROM DeliveryPerson Table to insert breadcrumb against particular Id
(DeliveryPerson.Name LIKE @name) OR ( DeliveryPerson.Email LIKE @name ) AND IsActive=1
Insert into @route
Select Id As RouteId,JobId from Route With(Nolock) where CarrierID=@deliveryBoyId AND JobId in( Select Id From Job where EndDate>=Convert(date,GETDATE())AND IsActive=1) 
AND TotalAddressPoint>0
order by Id desc --Inserting all the active jobs assigned to that carrier and also checking if addresspoint count is greater than 0.It means we are taking those Jobs whose addressPoint count is greater than 0.
Declare @J INT;
DECLARE @totalRouteCount INT;
SET @J=1;--Iterator variable
SELECT @totalRecords = COUNT(Point) FROM @points--taking count of all the addresspoints coming from Mobile device.
print @totalRecords
print @totalRouteCount
SELECT @totalRouteCount=Count(*) FROM @route --taking count of all the active Jobs/Routes of Jobs assigned to carrier
print @totalRouteCount
DECLARE @addressPoint geography;
DECLARE @speed bigint;
DECLARE @direction nvarchar(100);
DECLARE @capturedFrom nvarchar(100);
DECLARE @accuracy decimal;
DECLARE @isDisconnectedPoint bit
SET @I=1;
WHILE (@I <= @totalRecords)
BEGIN
Select @addressPoint=GEOGRAPHY::STGeomFromText (points.Point,4326),@speed=points.Speed,@direction=points.Direction,
@capturedFrom=points.CapturedFrom,@accuracy=points.Accuracy ,
@isDisconnectedPoint= points.IsDisconnect,@accuracy=points.Accuracy from @points points where points.Id=@I 
Insert into Tracking(CarrierId,Point,Speed,Direction,CapturedFrom,CapturedAt,Accuracy,IsDisconnect,CreatedOn,IsActive) --inserting mobile addresspoint to Tracking table.
Values(@deliveryBoyId,
@addressPoint,
(@speed*2.237)
,@direction,
@capturedFrom   ,
CONVERT(VARCHAR(23), (Select points.CapturedAt from @points points where points.Id=@I), 121),
@accuracy,
@isDisconnectedPoint
,GETDATE()
,1
)
SELECT TOP 1 @trackingId=Id from Tracking order by Id desc
if(@totalRouteCount>0)
BEGIN
SET @j=1;
Insert into Delivery(AddressPointId,TrackingId,RouteId,JobId,CreatedOn,IsActive)
Select (address.Id),@trackingId,rJob.RouteId,rJob.JobId,GetDate(),1
FROM ExistingAddressPointTable address JOIN @route rJob ON rJob.RouteId=address.RouteJobID 
where address.point.STDistance(@addressPoint)<200 
AND address.IsDelivered=0--Non spatial table but still this is 2nd highest CPU usage query.Frankly speaking,I dont know why.

update addres
set addres.IsDelivered =1
from ExistingAddressPointTable addres inner join @routeJob rout on addres.RouteId = rout.RouteId
where addres.point.STDistance(@addressPoint)<200 --Table have 15 millions record now.In azure server this query takes huge CPU spike
AND addres.IsDelivered=0
END
SET @I=@I+1;
END
IF(@isDisConnected=1)--Updating delivery boy status to deactivate mode to his last  tracking record.
BEGIN
Select TOP 1 @trackingId=Id from Tracking where DeliveryBoyId=@deliveryBoyId AND IsActive=1 Order by Id desc
Update Tracking set IsDisconnect=1 where Id=@trackingId
END
END

1 Ответ

0 голосов
/ 13 мая 2019

Попробуйте заменить это:

        Insert into Delivery(AddressPointId,TrackingId,RouteId,JobId,CreatedOn,IsActive)
        Select (address.Id),@trackingId,rJob.RouteId,rJob.JobId,GetDate(),1
        FROM ExistingAddressPointTable address JOIN @route rJob ON rJob.RouteId=address.RouteJobID 
        where address.point.STDistance(@addressPoint)<200 
        AND address.IsDelivered=0--Non spatial table but still this is 2nd highest CPU usage query.Frankly speaking,I dont know why.

        update addres
        set addres.IsDelivered =1
        from ExistingAddressPointTable addres inner join @routeJob rout on addres.RouteId = rout.RouteId
        where addres.point.STDistance(@addressPoint)<200 --Table have 15 millions record now.In azure server this query takes huge CPU spike
        AND addres.IsDelivered=0

на этот код:

        Select address.Id,@trackingId as TrackingId,rJob.RouteId,rJob.JobId,GetDate() as CreatedOn,1 as IsActive, address.point
        into #temp
        FROM ExistingAddressPointTable address JOIN @route rJob ON rJob.RouteId=address.RouteJobID 
        AND address.IsDelivered=0

        delete from #temp
        where point.STDistance(@addressPoint)>=200 

        Insert into Delivery(AddressPointId,TrackingId,RouteId,JobId,CreatedOn,IsActive)
        Select Id, TrackingId, RouteId, JobId, CreatedOn, IsActive
        from #temp as Temp

        update addres
        set addres.IsDelivered =1
        from ExistingAddressPointTable addres
        where Id in (Select Id from #temp)

Если загрузка вашего ЦП снизится, проблема заключалась в том, что сервер рассчитал расстояние для каждой строки,независимо от того, было ли isDelivered равно 0 или 1. Также address.IsDelivered должен иметь индекс.

В общем, если у вас проблемы с производительностью, попробуйте сузить его до точного утверждения, комментируя части кода или ведя логивремя между командами.

...