Re: [MSSQL] Как будет быстрее?
От: Antipov  
Дата: 25.01.06 09:37
Оценка:
Здравствуйте, _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 и переписать запрос в тригере.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.