Должен ли я использовать уникальный идентификатор для строки в соединительной таблице? - PullRequest
2 голосов
/ 04 октября 2011

Я использую SQL Server 2008.

Некоторое время назад я задал вопрос "должен ли я использовать RecordID в соединительной таблице". Таблицы будут выглядеть так:

// Images
ImageID// PK

// Persons
PersonID // pk

// Images_Persons
RecordID // pk
ImageID // fk
PersonID // fk

Я настоятельно рекомендовал НЕ использовать RecordID, потому что он бесполезен в таблице, где два идентификатора создают уникальную комбинацию, что означает, что не будет повторяющихся записей.

Теперь я пытаюсь найти случайную запись в соединительной таблице, чтобы создать тест. Я хочу вытащить первый идентификатор и посмотреть, сможет ли кто-нибудь сопоставить второй идентификатор. В частности, я беру случайное изображение и показываю его с тремя вариантами выбора.

Следующий запрос работает, но я немного негативен, что говорит о том, что он очень медленный. В моей базе данных может быть 10 000 записей, поэтому я не думаю, что это имеет большое значение. Я также читал, что сгенерированные значения не являются действительно случайными.

SELECT TOP 1 * FROM Images_Persons ORDER BY newid();

Должен ли я добавить столбец RecordID или нет? Есть ли лучший способ найти случайную запись в этом случае?

Предыдущие вопросы для справки

Ответы [ 3 ]

2 голосов
/ 04 октября 2011

Лично я не думаю, что наличие столбца RecordID следует рекомендовать ПРОТИВ.Скорее, я бы советовал, что часто это НЕОБХОДИМО.

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


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

ПричинаЯ говорю это потому, что ваше предлагаемое решение требует присвоения NEWID () каждой записи и сортировки всех записей, чтобы найти первую.По мере увеличения размера таблицы эта операция увеличивается и может стать относительно дорогой.Достаточно ли дорого стоит оптимизация, зависит от того, что еще происходит, как часто и т. Д.

Однако при наличии последовательных последовательных уникальных идентификаторов можно выбрать случайное значение между MIN (id) и MAX.(id), а затем ИСКАТЬ это значение.Требование, чтобы все значения были последовательными, однако, часто является слишком большим ограничением;вам никогда не разрешается удалять среднюю таблицу значений, например ...

Чтобы преодолеть это и в зависимости от индексов, вы можете найти следующий подход полезным.

DECLARE
  @max_id INT
SELECT
  @id = COUNT(*)
FROM
  Images_Persons

SELECT
  *
FROM
(
  SELECT
    *,
    ROW_NUMBER() OVER (ORDER BY ImageID, PersonID) AS id
  FROM
    Images_Persons
)
  AS data
WHERE
  Images_Persons.id = CAST(@max_id * RAND() + 1 AS INT)

-- Assuming that `ImageID, PersonID` is the clustered index.

Недостатком является то, что RAND () печально известен своей случайностью.Тем не менее, он обычно идеально подходит, если выполняется в произвольное время относительно любого другого вызова RAND ().

2 голосов
/ 04 октября 2011
  1. NEWID достаточно случайный и, вероятно, лучший
  2. 10 000 строк - это арахис
  3. Вам не нужен суррогатный ключ для таблицы соединений (ссылка, многие-многие)

Редактировать: если вы хотите преждевременно оптимизировать ...

Вы можете проигнорировать это и прочитать их из @Mitch Wheat.Но только с 10 тыс. Строк ваше время разработки будет больше, чем любое сохраненное время выполнения.

0 голосов
/ 04 октября 2011

Подумайте, что у вас есть.

SELECT TOP 1 * FROM Images_Persons ORDER BY newid();

Не совсем случайно?Исключая бит «действительно случайный - невозможно», вы, вероятно, правы - я считаю, что в сгенерированных уникальных идентификаторах есть шаблоны.Но вы должны проверить это сами.Это было бы просто;просто создайте таблицу с 1 до 100, order by newid() много раз, и посмотрите на результаты.Если это случайное «достаточно» для вас (что, вероятно, будет для викторины), то это достаточно хорошо.

Очень медленно?Я бы не беспокоился об этом.Я был бы очень удивлен, если newid() медленнее, чем чтение записи из таблицы.Но опять же, тестируйте и тестируйте.

Я был бы рад вашему решению, ожидая тестов, если вас это беспокоит.

Я всегда использовал order by newid().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...