|   |   | 
| 
 | А интересно как вы удаляете строки из таблицы значений. | ☑ | ||
|---|---|---|---|---|
| 0
    
        Keyn 05.01.16✎ 08:49 | 
        А интересно как вы удаляете строки из таблицы значений. Надеюсь что не так: ТаблицаЦен.Удалить(Индекс); (взял пример из хелпа)
 Работать конечно будет просто медленно. Когда вы удаляете так как в хелпе, то 1Ска удалит строку и сдвинет остальные строки "вверх". А это медленный процесс. Если у вас большая таблица значений и удалить нужно много строк, это может занять время, а ждать не хочется, поэтому можно воспользоватся хитростью. Добавляем в таблицу значений новую служебную колонку. В эту колонку каждому удаляемому значению ставим 1. Затем сортируем по этой колонке и все удаляемые значения окажутся в конце. (сортировка же делается быстро) Затем спокойно удаляем все начиная с конца, и в этом случае 1Ске не придется "сдвигать" строки. И такое удаление будет быстрым. Вот такой код у меня получился: // Очень быстро! Удаляет строки из таблицы значений, но только те строки в которых есть переданное значение // ТЗ - таблица значений // Колонка - идентификатор колонки в которой будет осуществлятся поиск Значения. // Значение - значение которое будем удалять // ЗначениеОставить - 1 означает что нужно оставить в таблице переднанное Значение, а остальные удалить // 0 наоборот, удалить из таблицы переданное Значение Процедура УдалитьСтрокиИзТЗ(ТЗ,Колонка,Значение,ЗначениеОставить=0) Экспорт НадаУдалять=0; ТЗ.Колонки.Добавить("СЛУЖДЛЯУДАЛЕНИЯ"); Если ЗначениеОставить=0 Тогда Для каждого СтрокаТЗ Из ТЗ Цикл Если СтрокаТЗ[Колонка]=Значение Тогда СтрокаТЗ.СЛУЖДЛЯУДАЛЕНИЯ=1; НадаУдалять=1; КонецЕсли; КонецЦикла; Иначе Для каждого СтрокаТЗ Из ТЗ Цикл Если СтрокаТЗ[Колонка]<>Значение Тогда СтрокаТЗ.СЛУЖДЛЯУДАЛЕНИЯ=1; НадаУдалять=1; КонецЕсли; КонецЦикла; КонецЕсли; Если НадаУдалять=1 Тогда ТЗ.Сортировать("СЛУЖДЛЯУДАЛЕНИЯ"); Индекс=ТЗ.Количество()-1; Пока Индекс>=0 Цикл Если ТЗ[Индекс].СЛУЖДЛЯУДАЛЕНИЯ=1 Тогда ТЗ.Удалить(Индекс); Иначе Прервать; КонецЕсли; Индекс=Индекс-1; КонецЦикла; КонецЕсли; ТЗ.Колонки.Удалить("СЛУЖДЛЯУДАЛЕНИЯ"); КонецПроцедуры писал код давно еще на заре выхода 8.0. и да я знаю как пишется слово надо | |||
| 1
    
        Маратыч 05.01.16✎ 08:51 | 
        А насколько быстрее, не замерялось? Чот терзают меня смутные сомнения, что весь этот комплект операций будет работать быстрее, чем некий "сдвиг" строк ТЗ в памяти при удалении через индекс.     | |||
| 2
    
        Рэйв 05.01.16✎ 08:52 | 
        у меня самый простой метод.Сначала нахожу все строки которые надо удалить и складываю их в список.
 Потом пробегаю список и Таб.Удалить(ЭлементСписка.Значение) | |||
| 3
    
        Рэйв 05.01.16✎ 08:52 | 
        ну или если возможно одним условием, то получаю в массив через .НайтиСтроки()     | |||
| 4
    
        Keyn 05.01.16✎ 08:53 | 
        конечно же замерялось. к сожалению не могу привести сейчас ссылку. но этот способ один из быстрых. есть и другие)     | |||
| 5
    
        tank68 05.01.16✎ 09:25 | 
        Можно не в запрос передать таблицу как переменную
 Ошибка = Ложь; Текст = "Загрузка почтовых ящиков, указанных сотрудниками на ВнешняяТаблицаДанных."; ЗапросПочтаНаВнешняяТаблицаДанных = Новый Запрос; ЗапросПочтаНаВнешняяТаблицаДанных.Текст = "ВЫБРАТЬ | dbo_UserEmail.LDAP, | ВЫБОР | КОГДА ЕСТЬNULL(dbo_UserEmail.EMail1, ""0"") = ""0"" | ТОГДА ЕСТЬNULL(dbo_UserEmail.EMail2, ""0"") | ИНАЧЕ ЕСТЬNULL(dbo_UserEmail.EMail1, ""0"") | КОНЕЦ КАК ПочтаВнешняяТаблицаДанных |ИЗ | ВнешнийИсточникДанных.Intraru.Таблица.dbo_UserEmail КАК dbo_UserEmail |ГДЕ | ВЫБОР | КОГДА ЕСТЬNULL(dbo_UserEmail.EMail1, ""0"") = ""0"" | ТОГДА ЕСТЬNULL(dbo_UserEmail.EMail2, ""0"") | ИНАЧЕ ЕСТЬNULL(dbo_UserEmail.EMail1, ""0"") | КОНЕЦ <> ""0"""; ПочтаНаВнешняяТаблицаДанных = ЗапросПочтаНаВнешняяТаблицаДанных.Выполнить().Выгрузить(); Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | UserEmail.LDAP КАК LDAP, | UserEmail.ПочтаВнешняяТаблицаДанных КАК ПочтаНаВнешняяТаблицаДанных |ПОМЕСТИТЬ ТаблицаСПочтой |ИЗ | &UserEmail КАК UserEmail | |ИНДЕКСИРОВАТЬ ПО | LDAP |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ФизическиеЛица.Ссылка, | ТаблицаСПочтой.LDAP, | ТаблицаСПочтой.ПочтаНаВнешняяТаблицаДанных |ИЗ | Справочник.ФизическиеЛица КАК ФизическиеЛица | ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаСПочтой КАК ТаблицаСПочтой | ПО ФизическиеЛица.LDAP = ТаблицаСПочтой.LDAP |ГДЕ | ТаблицаСПочтой.ПочтаНаВнешняяТаблицаДанных <> ФизическиеЛица.ЭлектроннаяПочтаВнешняяТаблицаДанных"; Запрос.УстановитьПараметр("UserEmail",ПочтаНаВнешняяТаблицаДанных); Таблица = Запрос.Выполнить(); Выборка = Таблица.Выбрать(); #Если ТолстыйКлиентОбычноеПриложение Тогда Процессор = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений; Процессор.ОтображатьПроцентВывода = Истина; Процессор.НачатьВывод(); Элемент = Новый ЭлементРезультатаКомпоновкиДанных; #КонецЕсли Колво = Выборка.Количество(); НомерПП = 0; Пока Выборка.Следующий() Цикл Попытка НомерПП = НомерПП+1; #Если ТолстыйКлиентОбычноеПриложение Тогда Состояние(" Обрабатывается "+НомерПП+ " из "+Колво); Элемент.ПроцентВывода = НомерПП/Колво*100; Процессор.ВывестиЭлемент(Элемент); #КонецЕсли Если НомерПП = Цел(НомерПП/100)*100 Тогда Сообщить(""+ТекущаяДата()+" Обработано:"+СокрЛП(НомерПП)); КонецЕсли; Об = Выборка.Ссылка.ПолучитьОбъект(); Об.ЭлектроннаяПочтаВнешняяТаблицаДанных = Выборка.ПочтаНаВнешняяТаблицаДанных; Об.Записать(); Исключение ТекстОшибки = (""+ТекущаяДата()+" Сотрудник "+СокрЛП(Выборка.Ссылка)+" почта на ВнешняяТаблицаДанных " + СокрЛП(Выборка.ПочтаНаВнешняяТаблицаДанных)+" ошибка: "+ОписаниеОшибки()); Сообщить("--------------------------------------"); Сообщить(ТекстОшибки,СтатусСообщения.ОченьВажное); Сообщить("--------------------------------------"); Ошибка = Истина; Текст = Текст+Символы.ПС+Символы.ПС+ТекстОшибки; КонецПопытки; //Сообщить("Для сотрудника "+СокрЛП(Выборка.Ссылка)+" необходимо указать почту " + СокрЛП(Выборка.ПочтаНаВнешняяТаблицаДанных)); КонецЦикла; #Если Клиент Тогда Процессор.ЗакончитьВывод(); #КонецЕсли | |||
| 6
    
        tank68 05.01.16✎ 09:26 | 
        (5) А в запросе соответственно с этой таблицей что угодно делать, в запросе это быстрее делается чем в цикле     | |||
| 7
    
        Маратыч 05.01.16✎ 09:30 | 
        Костылестроение 80 лвл...     | |||
| 8
    
        tank68 05.01.16✎ 09:31 | 
        (7) Попробуй миллион строк перебрать в цикле и попробуй отобрать запросом я посмотрю как быстрее получиться     | |||
| 9
    
        Мимохожий Однако 05.01.16✎ 09:40 | 
        (0)важно для чего используется эта таблица значений потом. Может быть, в дальнейшем идёт перебор и достаточно поставить фильтр и продолжить для обработки. На просторах инета есть куча примеров. Я так и не понял, для чего создана ветка.     | |||
| 10
    
        Маратыч 05.01.16✎ 09:49 | 
        (8) От постановки задачи зависит. Я вообще постараюсь не допустить миллиона строк в ТЗ еще на этапе получения этих данных.     | |||
| 11
    
        Euguln 05.01.16✎ 10:09 | 
        (0) Забавно, а сортировка процесс на порядок сложнее, чем сдвиг строк. Об этом не задумывался?     | |||
| 12
    
        SeraFim 05.01.16✎ 10:20 | 
        Если есть возмножность отобрать все удаляемые строки через НайтиСтроки(), то делаю через неё.
 В Противном случае - цикл в обратном направлении | |||
| 13
    
        User_Agronom 05.01.16✎ 10:34 | 
        За год, наверное, уже 10я тема про удаление строк из ТЗ.
 Чаще бывает только про очистку ТЗ. Сбивается ли выборка ? | |||
| 14
    
        tank68 05.01.16✎ 10:43 | 
        (10) Ну вообще если не делать через такие вещи платформа сама начинает оптимизировать запрос и не всегда оптимально поэтому временные таблицы в запросе в большинстве случаев гораздо быстрее работает чем перебирать данные в цикле
 http://catalog.mista.ru/public/153851/ Книга знаний: Временные таблицы в 8.1 | |||
| 15
    
        Garykom гуру 05.01.16✎ 10:43 | 
        (13) ну не умеют поиском пользоваться. поэтому и не знают что самый быстрый способ удаления строк, это создание новой ТЗ с переносом туда тех что не нужно удалять     | |||
| 16
    
        tank68 05.01.16✎ 10:47 | 
        (15) Все надеяться что в новой версии что то новое не описанное ранее     | |||
| 17
    
        Живой Ископаемый 05.01.16✎ 11:01 | ||||
| 18
    
        strange2007 05.01.16✎ 11:47 | 
        Не понимаю в чём спор. Проверить то можно минут за несколько.
 №1 (удаление без сортировок, пернебирая каждую строку). 10000 записей: 0,083600 100000 записей: 0,930294 №2 (сначала пометка удаляемых строк, потом сортировка и удаление): 10000 записей: 0,088318 100000 записей: 0,935507 База файловая, платформа 8.3.7 | |||
| 19
    
        strange2007 05.01.16✎ 11:51 | 
        +(18) Код выложить? Как его жёлтый плюсик обернуть?     | |||
| 20
    
        Злопчинский 05.01.16✎ 12:22 | 
        Восьмерочники открывают для себя клюшечные азы
 Прикольненько | |||
| 21
    
        zak555 05.01.16✎ 12:25 | 
        (20) ты 17 посмотри     | |||
| 22
    
        strange2007 05.01.16✎ 12:34 | 
        (21) Смотрел. У автора был конкретный вопрос, тема уже более 3-х часов висит, вот я и сделал замер минут за 15 для автора     | |||
| 23
    
        zak555 05.01.16✎ 12:39 | 
        (22)  делай замер на
 ОбъектДокумента = Документ.ПолучитьОбъект(); КритерийОставленияСтрок = Новый Структура(); КритерийОставленияСтрок .Вставить("КакаяТаКолонка", КакоеТоЗначение) ОбъектДокумента.Товары.Загрузить(ОбъектДокумента.Товары.Загрузить(ОбъектДокумента.Товары.НайтиСтроки(КритерийОставленияСтрок))); | |||
| 24
    
        strange2007 05.01.16✎ 12:50 | 
        (23) Сам делай)))))) Я для (0) сделал и выложил результаты замеров. Если надо что-то кому-то доказать или оптимизировать свой алгоритм, то пусть сам и замеряет скорость.
 Эх, теоретики... | |||
| 25
    
        Nirvana 17.01.16✎ 00:15 | 
        Это в небольших таблицах значений сортировка делается быстро.
 А в огромных таблицах сортировка - чуть ли не самая медленная операция. | |||
| 26
    
        ifso 17.01.16✎ 01:05 | 
        (25) главное не озвучивай, что при сортировке строки сдвигаются, а то мало ли что ^^     | 
 
 | Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |