ALTER TABLE, не блокируя таблицу?

Я знаю, что этот вопрос слишком стар, но я не видел никакой реализации, подобной моей. Эта версия основана на символе преобразования Шварца .

function sortByAttribute(array, ...attrs) {
  // generate an array of predicate-objects contains
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // schwartzian transform idiom implementation. aka: "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i]) result = -1;
      if (o1.compareValues[i] > o2.compareValues[i]) result = 1;
      if (result *= predicates[i].descend) break;
    }
    return result;
  })
  .map(item => item.src);
}

Вот пример того, как его использовать:

let games = [
  { name: 'Pako',              rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// sort by one attribute
console.log(sortByAttribute(games, 'name'));
// sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

105
задан Daniel 21 January 2009 в 00:44
поделиться

9 ответов

Единственная другая опция состоит в том, чтобы сделать вручную, что много систем RDBMS делают так или иначе...
- Создают новую таблицу

, можно тогда скопировать содержание старой таблицы по блоку за один раз. Всегда будучи осторожным из любого ВСТАВЛЯЕТ/ОБНОВЛЯЕТ/УДАЛЯЕТ на исходной таблице. (Мог управляться триггером. Хотя это вызвало бы замедление, это не блокировка...)

Когда-то законченный, измените имя исходной таблицы, затем измените имя новой таблицы. Предпочтительно в транзакции.

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

РЕДАКТИРОВАНИЕ:

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

  • Добавление нового поля похоже на изменение одного поля на каждой строке.
  • Полевые Блокировки были бы намного более твердыми, чем Блокировки строки, не брать в голову блокировки таблицы.

  • Вы на самом деле изменяете физическую структуру на диске, каждая запись перемещения.
  • Это действительно похоже на ОБНОВЛЕНИЕ на таблице Whole, но с большим количеством влияния...
59
ответ дан Tom Morris 5 November 2019 в 10:59
поделиться

Едва ли.

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

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

-6
ответ дан Will Hartung 5 November 2019 в 10:59
поделиться

Фиктивные столбцы являются хорошей идеей, если можно предсказать их тип (и сделать их nullable). Проверьте, как Ваши дескрипторы механизма устройства хранения данных аннулируют.

MyISAM заблокирует все, если Вы даже упомянете имя таблицы мимоходом, по телефону, в аэропорту. Это просто делает это...

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

0
ответ дан SquareCog 5 November 2019 в 10:59
поделиться

В целом ответ будет "Нет". Вы изменяете структуру таблицы, которая потенциально потребует большого количества обновлений", и я определенно соглашаюсь с этим. Если Вы будете ожидать делать это часто, то я предложу альтернативу "фиктивным" столбцам - использование VIEW с вместо таблиц для SELECT данные луга. IIRC, изменяя определение представления относительно легок, и косвенность посредством представления сделана, когда план запросов компилируется. Расход - то, что необходимо было бы добавить столбец к новой таблице и сделать представление JOIN в столбце.

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

Просто мысль.

1
ответ дан Benjamin 5 November 2019 в 10:59
поделиться

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

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

2
ответ дан dkretz 5 November 2019 в 10:59
поделиться

Так как Вы спросили о других базах данных, вот некоторая информация о Oracle.

Добавление столбца NULL к таблице Oracle является очень быстрой операцией, поскольку оно только обновляет словарь данных. Это содержит монопольную блокировку на таблице в течение очень короткого периода времени. Это будет однако, делать недействительным любые depedant хранимые процедуры, представления, триггеры, и т.д. Они будут перекомпилированы автоматически.

Оттуда при необходимости можно создать индекс с помощью пункта ОНЛАЙН. Снова, только очень короткие блокировки словаря данных. Это считает целую таблицу, ища вещи индексировать, но не блокирует никого при выполнении этого.

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

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

Оттуда, можно сделать switcharoo на серверах приложений к новой версии кода, и это будет продолжать бежать. Отбросьте свой подлый триггер.

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

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

7
ответ дан WW. 5 November 2019 в 10:59
поделиться

Используя плагин Innodb, операторы ALTER TABLE, которые только добавляют или отбрасывают вторичные индексы, могут быть сделаны "быстро", т.е. не восстанавливая таблицу.

Вообще говоря, однако, в MySQL, любой ALTER TABLE включает восстановление всей таблицы, которая может занять очень долгое время (т.е. если таблица имеет полезный объем данных в ней).

действительно необходимо разработать приложение так, чтобы операторы ALTER TABLE не должны были регулярно делаться; Вы, конечно, не хотите ALTER TABLE, сделанного во время нормального выполнения приложения, если Вы не готовы ожидать, или Вы изменяете крошечные таблицы.

1
ответ дан MarkR 5 November 2019 в 10:59
поделиться

Я рекомендовал бы один из двух подходов:

  1. Дизайн Ваши таблицы базы данных с потенциалом изменяется в памяти. Например, я работал с Системами управления контентом, которые изменяют поля данных в содержании регулярно. Вместо того, чтобы создать физическую структуру базы данных для соответствия начальным требованиям поля CMS намного лучше создать в гибкой структуре. В этом случае, с помощью текстового поля блоба (varchar (макс.), например) для содержания гибких данных XML. Это делает структурные изменения очень менее частыми. Структурные изменения могут быть дорогостоящими, таким образом, существует преимущество для стоения здесь также.

  2. Имеют время обслуживания системы. Любой система идет офлайн во время изменений (ежемесячно, и т.д.), и изменений, планируется в течение наименее в большой степени переданного времени дня (3-5am, например). Изменения подготавливаются до производственного развертывания, таким образом, у Вас будет хорошая фиксированная оценка окна времени простоя.

2a. Имейте избыточные серверы, так, чтобы, когда система имеет время простоя, целый сайт не понижался. Это позволило бы Вам "развертывать" свои обновления ступенчатым способом, не удаляя целый сайт.

Опции 2 и 2a не могут быть выполнимыми; они имеют тенденцию быть только для более крупных сайтов/операций. Они - допустимые опции, однако, и я лично использовал все опции, представленные здесь.

1
ответ дан pearcewg 5 November 2019 в 10:59
поделиться

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

  • подождать, пока все изменения будут реплицированы на пассивное ведомое устройство
  • сменить пассивное ведомое устройство на активное ведущее устройство
  • выполнить структурные изменения на старом ведущем устройстве
  • реплицировать изменения обратно с нового ведущего устройства на старое ведущее устройство
  • снова выполнить смену ведущего устройства и развертывание нового приложения одновременно

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

3
ответ дан 24 November 2019 в 04:00
поделиться
Другие вопросы по тегам:

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