Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Есть таблица типа такой:

CREATE TABLE [dbo].[cache]
(
	[key_int] [int] IDENTITY(1,1) NOT NULL,
	[cachekey] [nvarchar](4000) NULL,
	[result] [nvarchar](max) NULL,
	[hashkey]  AS (hashbytes('MD5',[cachekey])),
)


[key_int] - вообще не относится к предметной области.

Реальный ключ - это cachekey.

Есть ли смысл объявить его ПК или можно как-то извернуться и сделать покороче ключ? как?
21 июл 15, 10:54    [17915947]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
iap
Member

Откуда: Москва
Сообщений: 47000
Winnipuh,

индексировать можно только до 900 байт строки.
Делать надо суррогатный PK, и больше на этом не заморачиваться.
21 июл 15, 11:01    [17915979]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
iap
Winnipuh,

индексировать можно только до 900 байт строки.
Делать надо суррогатный PK, и больше на этом не заморачиваться.


да, про 900 я помню, можно обрезать на крайняк.

как суррогатный в данном случае?

может вообще без ключа, а проиндексировать по hashkey?
21 июл 15, 11:07    [17916020]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Glory
Member

Откуда:
Сообщений: 104760
Winnipuh
да, про 900 я помню, можно обрезать на крайняк.

Какой же это тогда "реальный ключ", если если его можно просто так уменьшить в 4 раза ?
21 июл 15, 11:11    [17916047]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
o-o
Guest
Winnipuh
как суррогатный в данном случае?

так вот же уже суррогатный готовый
[key_int] [int] IDENTITY(1,1) NOT NULL
21 июл 15, 11:17    [17916087]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
o-o
Guest
ну в смысле срочно его объявить ПК,
пока не навставляли повторных через SET IDENTITY_INSERT ON
21 июл 15, 11:18    [17916099]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Glory
Winnipuh
да, про 900 я помню, можно обрезать на крайняк.

Какой же это тогда "реальный ключ", если если его можно просто так уменьшить в 4 раза ?


это отдельная тема, предположим с извращениями, но можно
21 июл 15, 11:20    [17916111]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Glory
Member

Откуда:
Сообщений: 104760
Winnipuh
это отдельная тема, предположим с извращениями, но можно

Если можно, то тогда о чем вопрос ? Делайте 900 байт и индексируйте
21 июл 15, 11:22    [17916129]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
o-o
ну в смысле срочно его объявить ПК,
пока не навставляли повторных через SET IDENTITY_INSERT ON


да, добавил, но потом замучали сомнения, а толку?

Процесс такой: это некий кэш, в таблице есть записи,

На чтении процедура генерирует ключ и проверяет есть ли такая запись в кеше, если есть - читает.
На записи делается merge по ключу-строке.

В обоих случаях есть переменная со значением ключа, то есть формируется по тому же принципу.
Вот и подумалось, толку от этого идентити?
21 июл 15, 11:23    [17916138]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Glory
Winnipuh
это отдельная тема, предположим с извращениями, но можно

Если можно, то тогда о чем вопрос ? Делайте 900 байт и индексируйте


не хотелось бы извращений

В таком случае можно вообще не заморачиваться с ПК, а поиндексировать hashkey поле и двойным запросом обходиться?
21 июл 15, 11:25    [17916150]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Glory
Member

Откуда:
Сообщений: 104760
Winnipuh
а поиндексировать hashkey поле

А кто будет следить за hashkey ?
HashBytes (Transact-SQL)
Return Value
varbinary (maximum 8000 bytes)
21 июл 15, 11:27    [17916158]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37068
Во-первых, [hashkey] AS (cast(hashbytes('MD5',[cachekey]) as binary (16))
Во-вторых, надо для уменьшения вероятности коллизий добавить в ключ несколько байт от исходной строки, например left (cachekey, 5)
21 июл 15, 11:31    [17916175]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Glory
Winnipuh
а поиндексировать hashkey поле

А кто будет следить за hashkey ?
HashBytes (Transact-SQL)
Return Value
varbinary (maximum 8000 bytes)


а что за ним следить, он считается на основании ключа
21 июл 15, 11:39    [17916222]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Glory
Member

Откуда:
Сообщений: 104760
Winnipuh
Glory
пропущено...

А кто будет следить за hashkey ?
HashBytes (Transact-SQL)
Return Value
varbinary (maximum 8000 bytes)


а что за ним следить, он считается на основании ключа

Мда.Поэтому типа если результат превысит 900 байт, мы его тупо уменьшим до 900 байт ?
21 июл 15, 11:41    [17916232]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Glory
Winnipuh
пропущено...


а что за ним следить, он считается на основании ключа

Мда.Поэтому типа если результат превысит 900 байт, мы его тупо уменьшим до 900 байт ?


Нет, не совсем так, чтобы "тупо".
Ключ составляется из нескольких частей и т.д.
Но не хочется усложнять простую структуру, состоящую сейчас из одной таблицы.
21 июл 15, 11:49    [17916279]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Glory
Member

Откуда:
Сообщений: 104760
Winnipuh
Нет, не совсем так, чтобы "тупо".
Ключ составляется из нескольких частей и т.д.
Но не хочется усложнять простую структуру, состоящую сейчас из одной таблицы.

Так усеките ваше поле [cachekey] до 900 байт
21 июл 15, 11:53    [17916298]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31437
Winnipuh
Есть ли смысл объявить его ПК или можно как-то извернуться и сделать покороче ключ? как?
У вас же по любому нет другого выхода.

Раз у вас "На чтении процедура генерирует ключ и проверяет есть ли такая запись в кеше, если есть - читает.", то вы ищете по этому полю, значит, нужен индекс, значит, вы либо уменьшаете поле до максимально допустимого размера, либо не используете MSSQL для этой задачи.

Если же вы можете уменьшить поле, то, разумеется, в такой таблице его разумно сделать кластерным ключём.
21 июл 15, 12:28    [17916451]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
alexeyvg
Winnipuh
Есть ли смысл объявить его ПК или можно как-то извернуться и сделать покороче ключ? как?
У вас же по любому нет другого выхода.

Раз у вас "На чтении процедура генерирует ключ и проверяет есть ли такая запись в кеше, если есть - читает.", то вы ищете по этому полю, значит, нужен индекс, значит, вы либо уменьшаете поле до максимально допустимого размера, либо не используете MSSQL для этой задачи.

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


я могу, но надо это поле делить на неколько полей, в общем не так все красиво.

Сделал так:

CREATE TABLE [dbo].[cache](
	[key_int] [int] IDENTITY(1,1) NOT NULL,
	[cachekey] [nvarchar](4000) NULL,
	[result] [nvarchar](max) NULL,
	[hashkey] AS (cast(hashbytes('SHA1',[cachekey]) as binary (20))) PERSISTED,
	[creation_date] [datetime2](7) NOT NULL DEFAULT (getdate()),
	CONSTRAINT [PK_cache] PRIMARY KEY CLUSTERED ([key_int] ASC)
);
CREATE NONCLUSTERED INDEX [ix_cache_hashkey] ON [dbo].[search_cache]([hashkey] ASC) INCLUDE ([cachekey]);
END;


Вроде неплохо, правда в SQL2008 есть только SHA1, но думаю достаточно и его.
21 июл 15, 12:39    [17916500]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Bator
Member

Откуда: Порт пяти морей
Сообщений: 439
1. hashkey - кластерный индекс неуникальный (16 байт)
2. искать по полному соваднению hashkey и cachekey
21 июл 15, 12:43    [17916524]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31437
Winnipuh
Сделал так:

CREATE TABLE [dbo].[cache](
	[key_int] [int] IDENTITY(1,1) NOT NULL,
	[cachekey] [nvarchar](4000) NULL,
	[result] [nvarchar](max) NULL,
	[hashkey] AS (cast(hashbytes('SHA1',[cachekey]) as binary (20))) PERSISTED,
	[creation_date] [datetime2](7) NOT NULL DEFAULT (getdate()),
	CONSTRAINT [PK_cache] PRIMARY KEY CLUSTERED ([key_int] ASC)
);
CREATE NONCLUSTERED INDEX [ix_cache_hashkey] ON [dbo].[search_cache]([hashkey] ASC) INCLUDE ([cachekey]);
END;
Я бы сделал кластерный, согласен с Bator.
Иначе будут лукапы, или нужно включать в INCLUDE прочие поля, что по сути будет неотличимо от кластерного индекса..

Впрочем, это уже зависит от соотношения чтение/запись. Если почти не читают, больше пишут, то некластерный индекс лучше, и можно без INCLUDE ([cachekey]) - всё равно лукап делать.
21 июл 15, 13:08    [17916652]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
super-code
Member

Откуда:
Сообщений: 244
Winnipuh,

Кто сказал, что контрольная сумма SHA1 в двадцать байт влезает?
21 июл 15, 14:06    [17916982]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
super-code
Winnipuh,

Кто сказал, что контрольная сумма SHA1 в двадцать байт влезает?


имя не знаю, кто именно писал, но вот тут кто-то сказал

https://msdn.microsoft.com/en-us/library/ms174415.aspx

Allowed input values are limited to 8000 bytes. The output conforms to the algorithm standard: 128 bits (16 bytes) for MD2, MD4, and MD5; 160 bits (20 bytes) for SHA and SHA1; 256 bits (32 bytes) for SHA2_256, and 512 bits (64 bytes) for SHA2_512.
21 июл 15, 14:48    [17917246]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Bator
Member

Откуда: Порт пяти морей
Сообщений: 439
судя по мнемоническим названиям - больше читают.
без кластерного будут лукапы, а в инклюд разве можно больше 900 в сумме пихать?

alexeyvg
Winnipuh
Сделал так:

CREATE TABLE [dbo].[cache](
	[key_int] [int] IDENTITY(1,1) NOT NULL,
	[cachekey] [nvarchar](4000) NULL,
	[result] [nvarchar](max) NULL,
	[hashkey] AS (cast(hashbytes('SHA1',[cachekey]) as binary (20))) PERSISTED,
	[creation_date] [datetime2](7) NOT NULL DEFAULT (getdate()),
	CONSTRAINT [PK_cache] PRIMARY KEY CLUSTERED ([key_int] ASC)
);
CREATE NONCLUSTERED INDEX [ix_cache_hashkey] ON [dbo].[search_cache]([hashkey] ASC) INCLUDE ([cachekey]);
END;
Я бы сделал кластерный, согласен с Bator.
Иначе будут лукапы, или нужно включать в INCLUDE прочие поля, что по сути будет неотличимо от кластерного индекса..

Впрочем, это уже зависит от соотношения чтение/запись. Если почти не читают, больше пишут, то некластерный индекс лучше, и можно без INCLUDE ([cachekey]) - всё равно лукап делать.
21 июл 15, 16:51    [17917813]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
Bator
судя по мнемоническим названиям - больше читают.
без кластерного будут лукапы, а в инклюд разве можно больше 900 в сумме пихать?

alexeyvg
пропущено...
Я бы сделал кластерный, согласен с Bator.
Иначе будут лукапы, или нужно включать в INCLUDE прочие поля, что по сути будет неотличимо от кластерного индекса..

Впрочем, это уже зависит от соотношения чтение/запись. Если почти не читают, больше пишут, то некластерный индекс лучше, и можно без INCLUDE ([cachekey]) - всё равно лукап делать.


По идее да, больше должно быть чтений, на то и расчитано. Но многое будет зависеть от TTL и т.д.

Построил, создал - даже не квакнуло о 900 байтах.
Пустил тесты - все рабоатет.
21 июл 15, 17:12    [17917911]     Ответить | Цитировать Сообщить модератору
 Re: Длинная строка как Primary Key?  [new]
o-o
Guest
Winnipuh
Bator
судя по мнемоническим названиям - больше читают.
без кластерного будут лукапы, а в инклюд разве можно больше 900 в сумме пихать?

пропущено...


По идее да, больше должно быть чтений, на то и расчитано. Но многое будет зависеть от TTL и т.д.

Построил, создал - даже не квакнуло о 900 байтах.
Пустил тесты - все рабоатет.

Include nonkey columns in a nonclustered index
to avoid exceeding the current index size limitations of a maximum of 16 key columns
and a maximum index key size of 900 bytes
.
The Database Engine does not consider nonkey columns when calculating the number of index key columns or index key size.
Create Indexes with Included Columns
21 июл 15, 17:49    [17918084]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить