Здравствуйте, _spin_, Вы писали:
__>Делаю серверный спам-фильтр. Алгоритм анализа сообщений уже отработан, но вот возникла проблема с длительной работой.
__>В общих чертах, система выглядит так:
__>На вход поступает сообщение, для него считается набор коэффициентов, потом эти коэффициенты сравниваются с уже рассчитанными для других, пришедщих ранее сообщений. Если по выбранному критерию коэффициенты текущие совпадают с коэффициентами, имеющимися в списке — сообщение считается повтором, помечается как подозрительное на спам и его коэффициенты далее не учитываются. Если же совпадение не отмечено — коэффициенты заносятся в список и сообщение считается оригиналом.
__>Все коэффициенты хранятся в одной таблице:
__>__>CREATE TABLE CoefLst(
__>[ID] int IDENTITY(1,1) PRIMARY KEY CLUSTERED,
__>Coef1 float NOT NULL,
__>Coef2 float NOT NULL,
__>...
__>...
__>CoefN float NOT NULL,
__>AddDate datetime DEFAULT (getdate()) NOT NULL,
__>ParentID int NULL
__>)
__>
__>Для каждого нового сообщения необходимо выполнить сложное сравнение его коэффициентов со всеми записями в таблице и если результат сравнения "одниаковый найден" — выдать его "ID".
__>Критерий сравнения таков:
__>[pascal]
Логику лучше реализовывать на сервере
CREATE TRIGGER ins_rec ON [dbo].[CoefLst] FOR INSERT
AS
DECLARE @Coef1 float
DECLARE @Coef2 float
DECLARE @Coef3 float
DECLARE @id int
DECLARE @delta float
--Можно прочитать откуданибудь если хочется
SET @delta = 0.1
DECLARE ins_rec CURSOR FOR SELECT [Coef1], [Coef2], [Coef3], [id] FROM [inserted]
OPEN ins_rec
FETCH NEXT FROM ins_rec INTO @Coef1, @Coef2, @Coef3, @id
WHILE @@FETCH_STATUS = 0
BEGIN
IF EXISTS (SELECT [id] FROM CoefLst
WHERE (@Coef1 BETWEEN ([Coef1] - @delta) AND ([Coef1] + @delta)) AND
(@Coef2 BETWEEN ([Coef2] - @delta) AND ([Coef2] + @delta)) AND
(@Coef3 BETWEEN ([Coef3] - @delta) AND ([Coef3] + @delta)) AND
[id] <> @id --Запись кот. проверяется на спам уже в таблице
--Но в случае спама удалится при откате
)
BEGIN
ROLLBACK TRANSACTION
RAISERROR ('Error: ins_rec Спам', 15, 1)
RETURN
END
FETCH NEXT FROM ins_rec INTO @Coef1, @Coef2, @Coef3, @id
END
CLOSE ins_rec
DEALLOCATE ins_rec
GO
__>Сейчас система работает бодренько на 1000 сообщений, но когда доходит до 30 тыс. сообщений, то скорость обработки падает до 1 сообщения в секунду.
Сейчас на порядок быстрее и будет зависеть от скорости сервера
__>Как это можно исправить?
Твоё задание в качестве факультатива
Подсказки:
для начала:
CREATE TABLE CoefLst(
[ID] int IDENTITY(1,1) PRIMARY KEY CLUSTERED,
Coef float NOT NULL,
CoefType int NOT NULL,
AddDate datetime DEFAULT (getdate()) NOT NULL,
ParentID int NULL
)
затем добавить индекс на Coef и переписать запрос в тригере.