Каково повышение производительности Последовательного Гуида по стандартному Гуиду?

Вот трюк. Позволяет открыть REPL и определить класс:

scala> case class Foo(i: Int)
defined class Foo

и простую функцию, которая работает с этим классом:

scala> def fooToInt(foo: Foo) = foo.i
fooToInt: (foo: Foo)Int

переопределить класс:

scala> case class Foo(i: Int)
defined class Foo

и создать экземпляр:

scala> val foo = Foo(1)
foo: Foo = Foo(1)

Все, что осталось, - вызвать fooToInt:

scala> fooToInt(foo)
<console>:34: error: type mismatch;
 found   : Foo(in class $iwC)(in class $iwC)(in class $iwC)(in class $iwC)
 required: Foo(in class $iwC)(in class $iwC)(in class $iwC)(in class $iwC)
          fooToInt(foo)

Он выглядит знакомым? Еще один трюк, чтобы лучше понять, что происходит:

scala> case class Foo(i: Int)
defined class Foo

scala> val foo = Foo(1)
foo: Foo = Foo(1)

scala> case class Foo(i: Int)
defined class Foo

scala> def fooToInt(foo: Foo) = foo.i
<console>:31: error: reference to Foo is ambiguous;
it is imported twice in the same scope by
import INSTANCE.Foo
and import INSTANCE.Foo
         def fooToInt(foo: Foo) = foo.i

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

Если вы не хотите периодически :reset REPL state, вы должны отслеживать созданные вами сущности и, если изменения типов определений, убедитесь, что неопределенные определения не сохраняются (переписывайте вещи, если необходимо), прежде чем продолжить.

65
задан Mitch Wheat 1 September 2013 в 23:52
поделиться

6 ответов

GUID по сравнению с Последовательным GUID



А типичный шаблон это должно использовать Гуид в качестве PK для таблиц, но, как отнесено в других обсуждениях (см. Преимущества и недостатки ключей базы данных GUID / UUID ) существуют некоторые проблемы производительности.

Это - типичная последовательность Гуида

проблемы f3818d69-2552-40b7-a403-01a6db4552f7
7ce31615-fafb-42c4-b317-40d21a6a3c60
94732fc7-768e-4cf2-9107-f0953f6795a5


этого вида данных are:<
-

  • Широкие дистрибутивы значений
  • Почти randomically
  • Индексное использование очень, очень, очень плохо
  • Много листа, перемещающегося
  • , Почти каждый PK должен быть, по крайней мере, на не проблеме кластерного индекса
  • , происходит и на Oracle Server и на SQL Server



, возможное решение А использует Последовательный Гуид, которые сгенерированы следующим образом:

cc6466f7-1066-11dd-acb6-005056c00008
cc6466f8-1066-11dd-acb6-005056c00008
cc6466f9-1066-11dd-acb6-005056c00008


, Как генерировать их От кода C#:

[DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(out Guid guid);

public static Guid SequentialGuid()
{
    const int RPC_S_OK = 0;
    Guid g;
    if (UuidCreateSequential(out g) != RPC_S_OK)
        return Guid.NewGuid();
    else
        return g;
}


Преимущества

  • Лучшее использование индекса
  • Позволяет использование кластеризованных ключей (чтобы быть проверенным в сценариях NLB)
  • Меньше использования диска
  • , 20-25% увеличения производительности в минимуме стоят



Реальное измерение: Сценарий:

  • Гуид, сохраненный как UniqueIdentifier, вводит на гуиде SQL Server
  • , сохраненном как CHAR (36) на партии Oracle
  • операций вставки, обработанных в пакетном режиме вместе в единственной транзакции
  • С 1 до 100 с вставок в зависимости от таблиц Some таблицы
  • > 10 миллионов строк



, Лабораторное испытание †“тест SQL Server

VS2008, 10 параллельных пользователей, нет думает время, сравнивает процесса с 600, вставляет в пакет для раскладного стола
Стандартный Гуид
В среднем. Продолжительность процесса: 10.5 секунда
В среднем. Запрос на второй: 54.6
В среднем. Resp. Время: 0.26

Последовательный Гуид
В среднем. Продолжительность процесса: 4.6 секунда
В среднем. Запрос на второй: 87.1
В среднем. Resp. Время: 0.12

Результаты на Oracle (жаль, различный инструмент, используемый для теста) 1.327.613, вставляют на таблице с Гуидом Стандарта гуида PK

, 0.02 секунда. прошедшее время для каждого вставляет, 2.861 секунда. из процессорного времени, общего количества [1 191] 31.049 секунда. истекший

Последовательный Гуид , 0.00 секунда. прошедшее время для каждого вставляет, 1.142 секунда. из процессорного времени, общего количества [1 194] 3.667 секунда. истекший

файл DB последовательное время ожидания чтения передало от [1 195] 6.4 , миллионы ожидают события [1 196] 62.415 секунды к [1 197] 1.2 , миллион ожидает события [1 198] 11.063 секунды.

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

105
ответ дан Community 24 November 2019 в 15:12
поделиться

Я могу отсутствовать, что-то здесь (не стесняйтесь исправлять меня, если я), но я вижу очень мало преимущества в использовании последовательного GUID/UUID для первичных ключей.

точка из использования GUID или UUID по автопостепенному увеличению целых чисел:

  • Они могут быть созданы где угодно без [1 113] контакт с базой данных
  • , Они - идентификаторы, которые совершенно уникальны в рамках Вашего приложения (и в случае UUID, универсально уникальны)
  • , Учитывая один идентификатор, нет никакого способа предположить следующее или предыдущее (или даже любой другие допустимые идентификаторы) за пределами принуждения скота огромный ключевое пространство.

, К сожалению, с помощью предложения, Вы проигрываете весь те вещи.

Так, да. Вы сделали GUID лучше. Но в процессе, Вы выбросили почти все причины использовать их во-первых.

, Если Вы действительно хотите улучшить производительность, используйте стандартный автоувеличивающий целочисленный первичный ключ. Это предоставляет все преимущества, которые Вы описали (и больше) будучи лучше, чем 'последовательный гуид' почти каждым способом.

Это, скорее всего, получит downmodded в забвение, поскольку это конкретно не отвечает на Ваш вопрос (который, по-видимому, тщательно обрабатывается так, Вы могли ответить на него сами сразу), но я чувствую, что это - намного более важный момент для повышения.

52
ответ дан Dan 24 November 2019 в 15:12
поделиться

Если Вы потребность для использования последовательных ГУИДОВ SQL Server 2005 может генерировать их для Вас с эти NEWSEQUENTIALID() функция.

Однако , так как основное использование ГУИДОВ должно генерировать ключи (или альтернативные ключи), который не может быть предположен (например, чтобы избежать, чтобы люди, передающие предполагаемые ключи, ДОБРАЛИСЬ), я не вижу, насколько применимый они - то, потому что они так легко предполагаются.

От MSDN:

Важный:
, Если конфиденциальность является беспокойством, не используйте эту функцию. Возможно предположить значение следующего сгенерированного GUID и, поэтому, данные доступа, связанные с тем GUID.

4
ответ дан Sklivvz 24 November 2019 в 15:12
поделиться

Выезд РАСЧЕСКИ Jimmy Nilsson: тип GUID, где многие биты были заменены подобным метке времени значением. Это означает, что РАСЧЕСКИ могут быть заказаны, и, когда используется в качестве результата первичного ключа в меньшем количестве разделений индексной страницы при вставке новых значений.

он в порядке для использования uniqueidentifier (GUID) в качестве Первичного ключа?

3
ответ дан Mitch Wheat 24 November 2019 в 15:12
поделиться

Я не вижу, что потребность в уникальных ключах, чтобы быть отгадываемой или нет, передавая их от веб-UI или в некоторой другой части кажется плохой практикой отдельно, и я не вижу, если у Вас есть проблемы безопасности, как использование гуида может улучшить вещи (если это - использование вопроса реальный генератор случайных чисел с помощью надлежащих crypto функций платформы).
другие объекты покрыты моим подходом, последовательный гуид может быть сгенерирован от кода без потребности в доступе DB (также, если только для Windows), и это уникально во времени и пространстве.
И да, вопрос был поставлен с намерением ответа на него, чтобы дать людям, которые выбрали Guids для их PK способ улучшиться, использование базы данных (в моем случае позволил клиентам выдерживать намного более высокую рабочую нагрузку, не имея необходимость изменять серверы).

кажется, что проблемы безопасности много, в этом случае не используйте Последовательный Гуид или, лучше все еще, используйте стандартный Гуид для PK, которые пасуются назад и передают от Вашего UI и последовательного гуида для всего остального. Как всегда нет никакой абсолютной истины, я отредактировал также основной ответ для отражения этого.

1
ответ дан massimogentilini 24 November 2019 в 15:12
поделиться

Как уже сказал Массимогентилини, производительность можно улучшить при использовании UuidCreateSequential (при создании руководств в коде). Но факт, похоже, отсутствует: SQL Server (по крайней мере, Microsoft SQL 2005/2008) использует ту же функциональность, НО: сравнение / порядок Guids различаются в .NET и на SQL Server, что все равно вызовет больше операций ввода-вывода, потому что гиды будут заказаны неправильно. Чтобы правильно сгенерировать направляющие, упорядоченные для сервера sql (упорядочивание), вам необходимо сделать следующее (см. сравнение подробности):

[System.Runtime.InteropServices.DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(byte[] buffer);

static Guid NewSequentialGuid() {

    byte[] raw = new byte[16];
    if (UuidCreateSequential(raw) != 0)
        throw new System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error());

    byte[] fix = new byte[16];

    // reverse 0..3
    fix[0x0] = raw[0x3];
    fix[0x1] = raw[0x2];
    fix[0x2] = raw[0x1];
    fix[0x3] = raw[0x0];

    // reverse 4 & 5
    fix[0x4] = raw[0x5];
    fix[0x5] = raw[0x4];

    // reverse 6 & 7
    fix[0x6] = raw[0x7];
    fix[0x7] = raw[0x6];

    // all other are unchanged
    fix[0x8] = raw[0x8];
    fix[0x9] = raw[0x9];
    fix[0xA] = raw[0xA];
    fix[0xB] = raw[0xB];
    fix[0xC] = raw[0xC];
    fix[0xD] = raw[0xD];
    fix[0xE] = raw[0xE];
    fix[0xF] = raw[0xF];

    return new Guid(fix);
}

или эта ссылка или эта ссылка .

21
ответ дан 24 November 2019 в 15:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: