SQL2005, нужно на базе реализовать простой счётчик, который при обращении каждый раз возвращает увеличенное значение.
Требования:
1. Генерируемые значения должны быть уникальны
2. После генерации нового значение желательно что бы никаких блокировок на базе не оставалось
Сейчас это реализованно давольно тупо, одна таблица с одной колонкой и одним рядом в котором лежит значение текущее и хранимка которая его увеличивает, проблема в том, что после UPDATE-а этого значение ессно остаются висеть блокировки. Вот от них и надо как то избавиться. Думаем что возможно написать CLR стору, которая будет создавать новую конекцию и генерировать новое значение в ней а потом возвращать назад. Так как это будет новая конекция/транзакция локи будут сразу сняты после её окончания. Вот думаю:
1. Как лучше бы всё это реализовать
2. То что я придумал возможно?
3. То что я придумал извращение?
Единственно, я бы посмотрел, не нагрузит ли базу создание новых соединений по каждому чиху. Возможно, будет лучше повесить рядом с базой небольшой сервис секвенсоров, удерживающий соединение, а из хранимки обращаться к этому сервису.
Здравствуйте, Softwarer, Вы писали:
S>Здравствуйте, Tom, Вы писали:
S>Единственно, я бы посмотрел, не нагрузит ли базу создание новых соединений по каждому чиху. Возможно, будет лучше повесить рядом с базой небольшой сервис секвенсоров, удерживающий соединение, а из хранимки обращаться к этому сервису.
У нас не так часто это надо, вопрос скорее в том, ка кбы без геморно и быстрее это реализовать, сейчас есть счётчик, но он "не автономен"... Сервис — это слишком
Здравствуйте, Tom, Вы писали:
Tom>SQL2005, нужно на базе реализовать простой счётчик, который при обращении каждый раз возвращает увеличенное значение. Tom>Требования: Tom>1. Генерируемые значения должны быть уникальны Tom>2. После генерации нового значение желательно что бы никаких блокировок на базе не оставалось
см. функцию NEWSEQUENTIALID() — это уникальный GUID, такой же как от NewID(), но каждое следующее значение этой функции гарантировано больше предыдущего. Единственное ограничение просто так его вызвать нельзя он обязательно должен быть дефолтным констрейнтом в таблице. Получать вставленное значение можно через INSERT ... OUTPUT ... INTO.
Tom>Сейчас это реализованно давольно тупо, одна таблица с одной колонкой и одним рядом в котором лежит значение текущее и хранимка которая его увеличивает, проблема в том, что после UPDATE-а этого значение ессно остаются висеть блокировки.
А таблица с identity не катит, обязательно надо апдейтить?
Tom>2. То что я придумал возможно?
Да.
Tom>3. То что я придумал извращение?
Да.
IB>см. функцию NEWSEQUENTIALID() — это уникальный GUID, такой же как от NewID(), но каждое следующее значение этой функции гарантировано больше предыдущего. Единственное ограничение просто так его вызвать нельзя он обязательно должен быть дефолтным констрейнтом в таблице. Получать вставленное значение можно через INSERT ... OUTPUT ... INTO.
Нужен последовательный int, гуид не подходит, или я чего то не понял?
IB>А таблица с identity не катит, обязательно надо апдейтить?
Незнаю, возможно катит, как этим воспользоваться?
Здравствуйте, IB, Вы писали:
IB>см. функцию NEWSEQUENTIALID() — это уникальный GUID, такой же как от NewID(), но каждое следующее значение этой функции гарантировано больше предыдущего. Единственное ограничение просто так его вызвать нельзя он обязательно должен быть дефолтным констрейнтом в таблице. Получать вставленное значение можно через INSERT ... OUTPUT ... INTO.
Здравствуйте, Lloyd, Вы писали:
L>А что такое "больше" для гуида?
Тоже самое, что и для всего остального GUID1 < GUID2, при условии что GUID2 получили позже чем GUID1.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, Lloyd, Вы писали:
L>>А что такое "больше" для гуида? IB>Тоже самое, что и для всего остального GUID1 < GUID2, при условии что GUID2 получили позже чем GUID1.
не очень понятно как на основе NEWSEQUENTIALID можно счётчик реализовать, и как при его помощи от блокировок избавиться
Здравствуйте, Tom, Вы писали:
Tom>Нужен последовательный int, гуид не подходит, или я чего то не понял?
Кому нужен?
Tom>Незнаю, возможно катит, как этим воспользоваться?
Очень просто. Создается глобальная табличка с Identity столбцом. Когда нужно получить новый ID вставляешь туда что-нибудь и получаешь SCOPE_IDENTITY(). Блокировки до конца транзакции есть, но они никому не мешают можешь в этой же табличке еще какую-нибудь общую информацию хранить... Можешь подчищать ее периодически, как захочется.
NEWSEQUENTALGUID() в этом плане лучше тем, что никаких приседаний с дополнительными таблицами вообще не требует и его свойства распространяются на несколько серверов, при условии что на серверах есть сетевая карта.
Здравствуйте, Tom, Вы писали:
Tom>не очень понятно как на основе NEWSEQUENTIALID можно счётчик реализовать, и как при его помощи от блокировок избавиться
Во всех таблицах где тебе нужно использовать уникальное значение больше предыдущего объявляешь столбец (RowID uniqueidentifier DEFAULT NEWSEQUENTALGUID(), ...) все.
Во всех этих столбцах значения будут уникальные и больше предыдущих даже в других таких же таблицах.
Tom>>Нужен последовательный int, гуид не подходит, или я чего то не понял? IB>Кому нужен?
Мне в качестве счётчика нужен int а не GUID
Tom>>Незнаю, возможно катит, как этим воспользоваться? IB>Очень просто. Создается глобальная табличка с Identity столбцом. Когда нужно получить новый ID вставляешь туда что-нибудь и получаешь SCOPE_IDENTITY(). Блокировки до конца транзакции есть, но они никому не мешают можешь в этой же табличке еще какую-нибудь общую информацию хранить... Можешь подчищать ее периодически, как захочется.
Подчищать...( Хотя как вариант — вполне.
IB>NEWSEQUENTALGUID() в этом плане лучше тем, что никаких приседаний с дополнительными таблицами вообще не требует и его свойства распространяются на несколько серверов, при условии что на серверах есть сетевая карта.
DECLARE @id uniqueidentifier
SET @id = NEWSEQUENTIALID()
SELECT @id
Ошибка:
Msg 302, Level 16, State 0, Line 2
The newsequentialid() built-in function can only be used in a DEFAULT expression for a column of type 'uniqueidentifier' in a CREATE TABLE or ALTER TABLE statement. It cannot be combined with other operators to form a complex scalar expression.
Msg 302, Level 16, State 0, Line 3
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, Tom, Вы писали:
Tom>>не очень понятно как на основе NEWSEQUENTIALID можно счётчик реализовать, и как при его помощи от блокировок избавиться IB>Во всех таблицах где тебе нужно использовать уникальное значение больше предыдущего объявляешь столбец (RowID uniqueidentifier DEFAULT NEWSEQUENTALGUID(), ...) все. IB>Во всех этих столбцах значения будут уникальные и больше предыдущих даже в других таких же таблицах.
Понял, но не получиться, значение счётчика часто запрашивается из back end-а итп... Надо всё таки именно счётчик в прямом смысле.
Здравствуйте, Tom, Вы писали:
Tom>Мне в качестве счётчика нужен int а не GUID
Ну раз нужен...
Tom>Подчищать...( Хотя как вариант — вполне.
Всяко лучше чем отдельное подключение...
Tom>Ошибка:
Ты внимательно читаешь? Я же писал:
Единственное ограничение просто так его вызвать нельзя он обязательно должен быть дефолтным констрейнтом в таблице.
Плюс полезно смотреть документацию, прежде чем использовтаь...
Здравствуйте, Tom, Вы писали:
Tom>SQL2005, нужно на базе реализовать простой счётчик, который при обращении каждый раз возвращает увеличенное значение. Tom>Требования: Tom>1. Генерируемые значения должны быть уникальны Tom>2. После генерации нового значение желательно что бы никаких блокировок на базе не оставалось
Tom>Сейчас это реализованно давольно тупо, одна таблица с одной колонкой и одним рядом в котором лежит значение текущее и хранимка которая его увеличивает, проблема в том, что после UPDATE-а этого значение ессно остаются висеть блокировки. Вот от них и надо как то избавиться. Думаем что возможно написать CLR стору, которая будет создавать новую конекцию и генерировать новое значение в ней а потом возвращать назад. Так как это будет новая конекция/транзакция локи будут сразу сняты после её окончания. Вот думаю:
Tom>1. Как лучше бы всё это реализовать Tom>2. То что я придумал возможно? Tom>3. То что я придумал извращение?
Tom>Ы?
Если честно, я не знаю как это сделано в SQL2005. В Oracle есть такие объекты, которые зовут sequence. И достаточно сделать select <seq_name>.NEXTVAL into :XXX from dual; Можно еще делать select CURVAL.
Неужто майкрософты не стали делать такой простой удобный объект?
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, IB, Вы писали:
IB>>см. функцию NEWSEQUENTIALID() — это уникальный GUID, такой же как от NewID(), но каждое следующее значение этой функции гарантировано больше предыдущего. Единственное ограничение просто так его вызвать нельзя он обязательно должен быть дефолтным констрейнтом в таблице. Получать вставленное значение можно через INSERT ... OUTPUT ... INTO.
L>А что такое "больше" для гуида?
Здравствуйте, _d_m_, Вы писали:
IB>>>см. функцию NEWSEQUENTIALID() — это уникальный GUID, такой же как от NewID(), но каждое следующее значение этой функции гарантировано больше предыдущего. Единственное ограничение просто так его вызвать нельзя он обязательно должен быть дефолтным констрейнтом в таблице. Получать вставленное значение можно через INSERT ... OUTPUT ... INTO.
L>>А что такое "больше" для гуида?
___>GUID — это целое 16-байтное число
Неужели? А nvarchar(100) — это наверное целое двухсотбайтное число?
Au1>Если честно, я не знаю как это сделано в SQL2005. В Oracle есть такие объекты, которые зовут sequence. И достаточно сделать select <seq_name>.NEXTVAL into :XXX from dual; Можно еще делать select CURVAL.
Au1>Неужто майкрософты не стали делать такой простой удобный объект?
Неа, был бы Оракл вопрос бы не возникнул
Здравствуйте, Lloyd, Вы писали:
L>>>А что такое "больше" для гуида?
___>>GUID — это целое 16-байтное число
L>Неужели? А nvarchar(100) — это наверное целое двухсотбайтное число?
Надо признавать свои ошибки, а не упорствовать в невежестве. Вот дернул тебе несколько ссылок, что впрочем, ты мог сделать и сам:
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, Lloyd, Вы писали:
L>>А что такое "больше" для гуида? IB>Тоже самое, что и для всего остального GUID1 < GUID2, при условии что GUID2 получили позже чем GUID1.
а гарантирует ли сервер, что следующий GUID будет сгенерирован "позже" предыдущего,
а если это произойдет "условно одновременно"?