powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Подскажите, как лучше организовать первичный ключ.
22 сообщений из 22, страница 1 из 1
Подскажите, как лучше организовать первичный ключ.
    #38621594
__TT__TT__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется таблица [Operation], в которой на данный момент 985+ млн. записей. В таблице есть первичный ключ – bigint identity. Он также является внешним, для 6 таблиц связанных с [Operation]. В таблице [Operation] есть 4 поля определяющие уникальность (код подразделения – int, код офиса – int, дата – date, номер операции в течение дня – int).
Есть задача: создать первичный ключ на основании 4 полей определяющих уникальность и заменить им имеющийся.
Сама задача трудностей не вызывает, предполагается создать поле numeric(28,0), для которого внешние приложение будет формировать ключ из полей определяющих уникальность, например так: PPPPOOOOOYYYYMMDDNNN,
Где:
PPPP – код подразделения, значения всегда положительные, максимальное значение 9999, фактически значений на данный момент 4, ранее было 47;
OOOOO – код офиса, значения всегда положительные, максимальное значение 99999, фактически офисов 1500 штук;
YYYY – номер года;
MM – номер месяца;
DD – номер дня;
NNN – номер операции в течение дня, значения всегда положительные, первая операция в дне начинается с 1, количество операций зависит от офиса, и может достигать 2 млн.
СУБД Microsoft SQL Server 2012 – 11.0.2218.0 (X64) Enterprise (Build 7601: Service Pack 1).
Вопрос № 1: в какой последовательности лучше расположить PPPP, OOOOO, YYYY, MM, DD, NNN?
Вопрос № 2: возможно есть альтернативное решение?
ЗюЫю Все затевается ради того, чтобы обеспечить BulkInsert из внешнего приложения, и исключить вставку записи с последующим запросом значения ключа, чтобы обеспечить наличие внешнего ключа для вставки данных в связанные таблицы.
Благодарю за помощь.

Модератор: Тема перенесена из форума "Microsoft SQL Server".
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38621693
Кот Матроскин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__Вопрос № 1: в какой последовательности лучше расположить PPPP, OOOOO, YYYY, MM, DD, NNN?

Зависит от того, в какой последовательности Вы грузите данные. Общая рекомендация - максимально стараться сделать ключ
монотонно возрастающим при операциях загрузки.
__TT__TT__Вопрос № 2: возможно есть альтернативное решение?

Есть - сделать нормальный Unique constraint на эти 4 поля, сгенеренный ключ для вставки в дочерние таблицы получать соединением по 4ем полям.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38621974
__TT__TT__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кот Матроскин,

извините, уточню, я правильно понял - нужно использовать естественные ключи?
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38622435
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__Имеется таблица [Operation], в которой на данный момент 985+ млн. записей. В таблице есть первичный ключ – bigint identity. Он также является внешним, для 6 таблиц связанных с [Operation]. В таблице [Operation] есть 4 поля определяющие уникальность (код подразделения – int, код офиса – int, дата – date, номер операции в течение дня – int).
Есть задача: создать первичный ключ на основании 4 полей определяющих уникальность и заменить им имеющийся.
Сама задача трудностей не вызывает, предполагается создать поле numeric(28,0), для которого внешние приложение будет формировать ключ из полей определяющих уникальность, например так: PPPPOOOOOYYYYMMDDNNN,
Где:
PPPP – код подразделения, значения всегда положительные, максимальное значение 9999, фактически значений на данный момент 4, ранее было 47;
OOOOO – код офиса, значения всегда положительные, максимальное значение 99999, фактически офисов 1500 штук;
YYYY – номер года;
MM – номер месяца;
DD – номер дня;
NNN – номер операции в течение дня, значения всегда положительные, первая операция в дне начинается с 1, количество операций зависит от офиса, и может достигать 2 млн.
СУБД Microsoft SQL Server 2012 – 11.0.2218.0 (X64) Enterprise (Build 7601: Service Pack 1).
Вопрос № 1: в какой последовательности лучше расположить PPPP, OOOOO, YYYY, MM, DD, NNN?
Вопрос № 2: возможно есть альтернативное решение?
ЗюЫю Все затевается ради того, чтобы обеспечить BulkInsert из внешнего приложения, и исключить вставку записи с последующим запросом значения ключа, чтобы обеспечить наличие внешнего ключа для вставки данных в связанные таблицы.
Т.е., фактически всё сводится к тому, чтобы первичный ключ генерировать во внешнем приложении. Самый простой способ, использовать GUID, генерируемый в приложении, можно даже последовательный, хотя это некритично, если не собираетесь по нему делать кластерный индекс.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38622445
Фотография Ennor Tiegael
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__,

На случай, если вы не в курсе, внешний ключ может ссылаться на более чем 1 поле таблицы. Конкретно в MSSQL - до 16 включительно.

Насколько я понимаю, у вас уже есть натуральный ключ из 4 полей в Operations; ну так переведите форейны на него, вместо идентити. Понятно, что джойны начнут выглядеть несколько устрашающе, но с точки зрения сиквела разницы будет немного.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38622662
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__,

Есть задача: создать первичный ключ на основании 4 полей определяющих уникальность и заменить им имеющийся.


Очень зря.
Создать можно другой ключ, альтернативный. Уникальный, если надо. Но заменять им первичный — это лишнее, и неправильно.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38622677
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__,

Сама задача трудностей не вызывает, предполагается создать поле numeric(28,0), для которого внешние приложение будет формировать ключ из полей определяющих уникальность, например так: PPPPOOOOOYYYYMMDDNNN,


Это — вообще идиотизм, граничащий с саботажем. Не говоря уже о нарушении 1НФ.

Чем составной ключь не устраивает?
Он ничуть не хуже , даже лучше .
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38622702
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__,

Вопрос № 1: в какой последовательности лучше расположить PPPP, OOOOO, YYYY, MM, DD, NNN?


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


Вопрос № 2: возможно есть альтернативное решение?

Да. Не страдать хреновней, создать составной уникальный индекс из этих полей, если надо. PK оставить в покое.



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


Это все можно делать по другому.
Bulk можно вставлять в отдельную таблицу, затем переливать в главную.
Сгенерированный ключь можно получать тем же запросом, что и вставка.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38623224
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__Кот Матроскин,

извините, уточню, я правильно понял - нужно использовать естественные ключи?

НЕ нужно использовать естественные ключи.
Вот так-- правильно.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38626674
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivЧем составной ключь не устраивает?
Составной ключ устраивает только теоретиков, никогда не пытавшихся всерьёз поработать с ним на практике.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38626677
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__Есть задача: создать первичный ключ на основании 4 полей определяющих уникальность и заменить им имеющийся.
Если бы эту задачу принесли мне, я бы очень упорно ругался на тему "это неправильная задача и делать надо совсем иначе".

__TT__TT__ЗюЫю Все затевается ради того, чтобы обеспечить BulkInsert из внешнего приложения, и исключить вставку записи с последующим запросом значения ключа,
Для этого нужно, чтобы внешнее приложение само генерило значение ПК, для этого совершенно не обязательно путаться с естественными ключами и пытаться всунуть два миллиона значений в маску NNN. Как именно генерить - многие пользуются гуидами, если это по какой-то причине нежелательно, то никто не мешает реализовать счётчик самому или воспользоваться функционалом базы, например, сделать в левой табличке поле INCREMENT(1,1000000) // сделали одну вставку - имеем миллион доступных нам id.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38626697
Злой Бобр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вставлю и свои пять.
__TT__TT__... создать первичный ключ на основании 4 полей определяющих уникальность и заменить им имеющийся
С точки зрения теории (тут уже правильно говорили) проблем нет. Но вот на практике за подобное нада пальцы в двери.
__TT__TT__Все затевается ради того, чтобы обеспечить BulkInsert из внешнего приложения, и исключить вставку записи с последующим запросом значения ключа, чтобы обеспечить наличие внешнего ключа для вставки данных в связанные таблицы.
Т.е. внешнее приложение будет инсертить в вашу БД? Ну дык и пусть инсертит. Вы PK заполняйте автоматом, а внешнее приложение пусть инсертит без PK (оно у вас автоматом на 1 будет увеличиваться на каждом инсерте).
Если проблема с заполнением FK в связанных таблицах то выкладывайте схему и рассказывайте в чем именно проблема. Ну а мы расскажем что это совсем непроблема, и подскажем куда копать.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38626757
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarerMasterZivЧем составной ключь не устраивает?
Составной ключ устраивает только теоретиков, никогда не пытавшихся всерьёз поработать с ним на практике.

Че, все уже сказал? Или ещё что осталось умного? Топик может тогда прочтешь, иногда полезно...
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38628808
__TT__TT__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Злой Бобр,

Давайте попробую внести ясность в задачу. Наверное мой косяк, что сразу поленился расписать все детали.

И так, есть текстовые файлы, которые экспортируются из внешней системы. Описание типов и сути полей взято из документации к системе которая эти файлы и генерит. На основнии описания созданы 6 таблиц. Одна из них [Operation], остальные таблицы связаны с ней по FK.
В таблице [Operation] есть 4 поля определяющие уникальность (код подразделения – int, код офиса – int, дата – date, номер операции в течение дня – int), на них есть Nonclustered unique contraint, еще в таблице есть первичный ключ - bigint identity.

Внешнее приложение разбирает файлы и вставляет записи в таблицы. Проблема в том, что PK генерится в БД и чтобы его получить нужно сначала вставить запись, а потом запросить сгенеренный ID. В итоге получаются дерганье туда-сюда и весь импорт длится целую ночь.

Хочется перевести приложение на использование BulkInsert. Поэтому возник вопрос, как генерить ID, т.е. вместо Identity, как вариант было предложено в приложении генерить ID на основании уникальных полей. Сами уникальные поля так и оставить, а у PK убрать identity.

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

В общем в идеале нужно оставить все тот же bigint в качестве ПК, а приложение перевести на использование BulkInsert.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38628819
Кот Матроскин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__Злой Бобр,

Давайте попробую внести ясность в задачу. Наверное мой косяк, что сразу поленился расписать все детали.

И так, есть текстовые файлы, которые экспортируются из внешней системы. Описание типов и сути полей взято из документации к системе которая эти файлы и генерит. На основнии описания созданы 6 таблиц. Одна из них [Operation], остальные таблицы связаны с ней по FK.
В таблице [Operation] есть 4 поля определяющие уникальность (код подразделения – int, код офиса – int, дата – date, номер операции в течение дня – int), на них есть Nonclustered unique contraint, еще в таблице есть первичный ключ - bigint identity.

Внешнее приложение разбирает файлы и вставляет записи в таблицы. Проблема в том, что PK генерится в БД и чтобы его получить нужно сначала вставить запись, а потом запросить сгенеренный ID. В итоге получаются дерганье туда-сюда и весь импорт длится целую ночь.

Хочется перевести приложение на использование BulkInsert. Поэтому возник вопрос, как генерить ID, т.е. вместо Identity, как вариант было предложено в приложении генерить ID на основании уникальных полей. Сами уникальные поля так и оставить, а у PK убрать identity.

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

В общем в идеале нужно оставить все тот же bigint в качестве ПК, а приложение перевести на использование BulkInsert.

Как в файлах связаны сущности, попадающие в Operation и дочерние таблицы? Эти сущности тоже раскиданы по разным файлам или соединены в одном?
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38628855
__TT__TT__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кот Матроскин,

Файл один, данные в нем идут подряд.
Каждая операция начинается с определенного признака, допустим с цифры 1, дальше до конца строки идут данные, разделенные |
В следующей строке могут быть сущности относящиеся к операции, которые будут иметь свой признак, например 2, 3, 4, 5, 6, либо новая операция, которая опять же будет начинаться с 1|

выглядить примерно так

1|20.01.2014|1|5|1|238.0
2|5|7|3
3|Сквозная система|3.0
1|20.01.2014|1|5|2|33.44
3|Подсистема ...|777

Приложение делит строку по символам | и анализирует первый элемент, на его основании делается вывод куда вставлять данные. В общем-то логика не сложная.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38628904
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__Поэтому возник вопрос, как генерить ID, т.е. вместо Identity, как вариант было предложено в приложении генерить ID на основании уникальных полей. Сами уникальные поля так и оставить, а у PK убрать identity.
Ну вроде так и понимали.

Генерить на основе уникальных полей в принципе можно, но при этом вы влетаете в две стандартные неприятности: во-первых, размер получающегося поля, а во-вторых, в "пришли кривые неуникальные данные, которые как-то таки надо загрузить". Раз внешнее приложение разбирает и вставляет, мне кажется, ну совершенно никто не мешает ему использовать собственный счётчик, стартуя ну хотя бы с select max(id) - приложение-то почти наверняка будет работать в единственном экземпляре, коллизий не будет.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38628950
Кот Матроскин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__,

Я бы залил файл целиком BULK-ом в буферную таблицу
Код: sql
1.
2.
3.
4.
5.
create table Buffer
(type, /*Ваше первое поле, определяющее тип сущности*/, 
 data, /* все остальное*/ 
 Operationid, /*  некий ID  любого типа, хоть GUID*/,
 Sequence  /* автоинкремент, указывающий порядок строк*/)



где в поле OperationID (при помощи Sequence) проставил бы,
какая сущность относится к какой операции
Потом делал бы вставки рабочие таблицы в духе
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
Insert Operation (....)
select Operation_GetCodeDivision( b.data),  Operation_GetDate( b.data) , ...
from buffer
where type = 1


insert Operation_child1 (OperationID, ...)
Select op.OperationID, [ тут разбор поля data таблицы b2]
From Operation op  /* свежевставленная операция, из которой берем первичный ключ */
       join buffer b1  /* строка операции в буферной таблице */
       on  b1.type = 1 and
            Operation_GetCodeDivision( b1.data) = op.CodeDivision and
            Operation_GetDate( b1.data) = op.data and
            ....
       join buffer b2 /* строка дополнительной сущности нужного типа, относящейся к операции */
      on b1. OperationId = b2.OperationID
where b2.Type = 2


insert Operation_child2 (OperationID, ...)
Select op.OperationID, ...
...
where b2.Type = 3
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38629499
Злой Бобр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__,

Лично я вижу только 2 варианта:
- отдать генерацию ид приложению (я б на такое непошел по понятным причинам, хотя если это чисто справочные или стат данные которые невлияют на рабочий процесс то наверное обрезал доступ приложению на уровне таблиц только этим таблицам и пусть что хочет то и творится)
- написать процедуру в самом скуле (логику дерганья данных из файлов судя по всему вы знаете) и забыть о прокладке (приложении)
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38634585
Dmitry V. Liseev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Автогенерацию айдишников базой для нужной таблицы можно временно отключить и генерировать их в приложении.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38634611
Dmitry V. Liseev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Но, самый правильный вариант - использовать временную буферную таблицу, вставить туда, потом процедурой перелить в основную таблицу. Я недавно тренировался так базу ФИАС заливать. Там 20 млн. записей. Примерно 30 минут на заливку в буферную таблицу. И 2 минуты на переливку из неё в постоянную. Лил через медленную сеть, быструю, на той-же машине, где сервер, играл с памятью, дисками. Лил как порциями разного размера, так и разом. Максимум из BuilkInsert выжалось 15 тыс. записей в секунду.
...
Рейтинг: 0 / 0
Подскажите, как лучше организовать первичный ключ.
    #38637867
mad_nazgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__TT__TT__Имеется таблица [Operation], в которой на данный момент 985+ млн. записей. В таблице есть первичный ключ – bigint identity. Он также является внешним, для 6 таблиц связанных с [Operation]. В таблице [Operation] есть 4 поля определяющие уникальность (код подразделения – int, код офиса – int, дата – date, номер операции в течение дня – int).
Есть задача: создать первичный ключ на основании 4 полей определяющих уникальность и заменить им имеющийся.

Не надо трогать, то что работает.
Просто создайте составной ключ на эти четыре поля и в свойствах укажите уникальность.


Т.о. вы решите вашу задачу (проверка на уникальность 4 значений средствами БД)
Не нужно будет перестраивать структуру БД.

P.S. Холивар об преимуществах/недостатках естественных ключей будет долгим и нудным.
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Подскажите, как лучше организовать первичный ключ.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]