Вы можете поместить некоторые инструкции Java в цикл для инициализации коллекции:
List characters = new ArrayList() {
{
for (char c = 'A'; c <= 'E'; c++) add(c);
}
};
Random rnd = new Random();
List integers = new ArrayList() {
{
while (size() < 10) add(rnd.nextInt(1_000_000));
}
};
нет, SQL-сервер не будет откатывать удаление, это уже работало при остановке выполнения запросов. оракул требует явной поддержки запросов действия, или данные откатываются, но не mssql.
с SQL-сервером это не будет откатывать, если Вы не будете конкретно работать в контексте транзакции, и Вы откатываете ту транзакцию или завершения соединения без фиксировавшей транзакции. но я не вижу контекст транзакции в Вашем выше запроса.
Вы могли также попытаться реструктурировать свой запрос для создания удаления немного более эффективного, но по существу если спецификации поля не на должном уровне тогда, Вы могли бы застрять, переждав его.
продвижение, необходимо создать уникальный индекс на таблице, чтобы помешать себе иметь для прохождения через этого снова.
Ваш запрос не обертывается в транзакцию, таким образом, он не будет откатывать изменения, уже внесенные отдельными операторами удаления.
я конкретно протестировал это сам на моем собственном SQL Server с помощью следующего запроса, и таблица ApplicationLog была пуста даже при том, что я отменил запрос:
declare @count int
select @count = 5
WHILE @count > 0
BEGIN
print @count
delete from applicationlog;
waitfor time '20:00';
select @count = @count -1
END
Однако Ваш запрос, вероятно, займет много дней или недель, намного дольше тогда 15 часов. Ваша оценка, что можно обработать 2 000 записей каждые 6 секунд, является неправильной, потому что каждое повторение в цикле с условием продолжения возьмет значительно дольше с 17 миллионами строк тогда, это делает с 2 000 строк. Таким образом, если Ваш запрос не занимает значительно меньше тогда секунду для 2 000 строк, потребуются дни для всех 17 миллионов.
необходимо задать новый вопрос о том, как можно удалить дублирующиеся строки эффективно.
Если Вы не сделаете ничего явного о транзакциях тогда, то соединение будет в транзакции автоматической фиксации режим. В этом режиме каждый SQL-оператор считают транзакцией.
вопрос состоит в том, означает ли это, что отдельные SQL-операторы являются транзакциями и поэтому фиксируются, когда Вы идете, или рассчитывает ли внешний Цикл с условием продолжения как транзакция.
, кажется, нет никакого обсуждения этого в описании В ТО ВРЕМЯ КАК конструкция на MSDN. Однако, так как НЕКОТОРОЕ ВРЕМЯ оператор не может непосредственно изменить базу данных, казалось бы логичным, что это не делает , запускают транзакцию автоматической фиксации.
, Если никакие 'Неявные транзакции' был установлен, то каждое повторение в Вашем цикле фиксировало изменения.
для любого SQL Server возможно быть установленным с 'Неявными транзакциями'. Это - установка базы данных (по умолчанию ВЫКЛЮЧЕНО). У Вас могут также быть неявные транзакции в свойствах особого запроса в Studio управления (щелчок правой кнопкой в области запроса> опции) настройками по умолчанию в клиенте или оператором SET.
SET IMPLICIT_TRANSACTIONS ON;
Так или иначе, если бы это имело место, необходимо было бы все еще выполнить явную ФИКСАЦИЮ/ОТКАТ независимо от прерывания выполнения запросов.
<час>ссылка Неявных транзакций:
Я наследовал систему, которая имела логику, которую что-то как Ваш реализовало в SQL. В нашем случае мы пытались соединить строки с помощью нечеткого соответствия, которое имело подобные имена/адреса, и т.д., и что логика была сделана просто в SQL. В то время, когда я наследовал его, у нас было приблизительно 300 000 строк в таблице и согласно синхронизациям, мы вычислили, потребуется ГОД для соответствия им всем.
Как эксперимент для наблюдения, насколько быстрее я мог сделать это за пределами SQL я записал программу, чтобы вывести таблицу базы данных в плоские файлы, считать плоские файлы в программу C++, создать мои собственные индексы, и сделать нечеткую логику там, затем повторно импортировать плоские файлы в базу данных. То, что заняло ГОД в SQL, заняло приблизительно 30 секунд в приложении C++.
Так, мой совет, даже не пробуют то, что Вы делаете в SQL. Экспорт, процесс, переимпорт.
Как цикл Ваш запрос будет изо всех сил пытаться масштабироваться хорошо, даже с соответствующими индексами. Запрос должен быть переписан к отдельному оператору согласно предложениям в Ваш предыдущий вопрос на этом.
, Если Вы не выполняете его явно в транзакции, это будет только откатывать выполняющийся оператор.
УДАЛЯЕТ, которые были выполнены до этой точки, не будет откатываться.
<час>Как исходный автор рассматриваемый код , и выпускавший протест, что производительность будет иждивенцем на индексах, я предложил бы следующие объекты для ускорения этого.
RecordId лучше быть PRIMARY KEY. Я не имею в виду ИДЕНТИФИКАЦИОННЫХ ДАННЫХ, я имею в виду PRIMARY KEY. Подтвердите этот sp_help
использования, Некоторый индекс должен использоваться в оценке этого запроса. Фигура, которая из этих четырех столбцов имеет наименьшее количество повторений и индексирует это...
SELECT *
FROM MyTable
WHERE @long = longitude
AND @lat = latitude
AND @businessname = BusinessName
AND @phoneNumber = Phone
Прежде и После добавления этого индекса, проверьте план запросов, чтобы видеть, было ли индексное сканирование добавлено.
Я думаю, что этот запрос был бы намного более эффективным, если бы он был переписан с помощью однопроходного алгоритма с помощью курсора. Вы заказали бы Вам таблицу курсора долготой, широтой, BusinessName И @phoneNumber. You’d ступают через строки по одному. Если строка имеет ту же долготу, широту, businessname, и phonenumber как предыдущая строка, то удалите его.
Я вполне уверен, который является отрицательным. Иначе, какова точка транзакций была бы?
Я думаю, вам нужно серьезно подумать о своей методологии. Вам нужно начать думать наборами (хотя для повышения производительности вам может потребоваться пакетная обработка, но не построчно для таблицы из 17 миллионов записей).
Во-первых, все ли ваши записи имеют дубликаты? Я подозреваю, что нет, поэтому первое, что вам нужно сделать, это ограничить обработку только теми записями, которые имеют дубликаты. Поскольку это большая таблица, и вам может потребоваться выполнять удаление партиями с течением времени в зависимости от того, какая другая обработка происходит, вы сначала извлекаете записи, с которыми хотите иметь дело, в отдельную таблицу, которую затем индексируете. Вы также можете использовать временную таблицу, если собираетесь делать все это одновременно, не останавливая ее, иначе создайте таблицу в своей базе данных и в конце удалите ее.
Что-то вроде (Примечание. t написать статус создания индекса, я полагаю, вы можете найти это сами):
SELECT min(m.RecordID), m.longitude, m.latitude, m.businessname, m.phone
into #RecordsToKeep
FROM MyTable m
join
(select longitude, latitude, businessname, phone
from MyTable
group by longitude, latitude, businessname, phone
having count(*) >1) a
on a.longitude = m.longitude and a.latitude = m.latitude and
a.businessname = b.businessname and a.phone = b.phone
group by m.longitude, m.latitude, m.businessname, m.phone
ORDER BY CASE WHEN m.webAddress is not null THEN 1 ELSE 2 END,
CASE WHEN m.caption1 is not null THEN 1 ELSE 2 END,
CASE WHEN m.caption2 is not null THEN 1 ELSE 2 END
while (select count(*) from #RecordsToKeep) > 0
begin
select top 1000 *
into #Batch
from #RecordsToKeep
Delete m
from mytable m
join #Batch b
on b.longitude = m.longitude and b.latitude = m.latitude and
b.businessname = b.businessname and b.phone = b.phone
where r.recordid <> b.recordID
Delete r
from #RecordsToKeep r
join #Batch b on r.recordid = b.recordid
end
Delete m
from mytable m
join #RecordsToKeep r
on r.longitude = m.longitude and r.latitude = m.latitude and
r.businessname = b.businessname and r.phone = b.phone
where r.recordid <> m.recordID