|   |   | 
| 
 | v7: Медленно работает запрос SQLite | ☑ | ||
|---|---|---|---|---|
| 0
    
        Volodja 21.01.21✎ 14:52 | 
        В чем может быть причина? Не пойму.
 тз=СоздатьОбъект("ТаблицаЗначений"); ТаблицаЗамен.Выгрузить(тз,,,"СтароеЗначение"); тз.НоваяКолонка("ИИН","Строка",12); тз.ВыбратьСтроки(); Пока тз.ПолучитьСтроку()=1 Цикл _Элемент=тз.СтароеЗначение; тз.ИИН=_Элемент.ИИН; КонецЦикла; глБД_SQLite.УложитьТЗ(тз,"тзЗамены"); ТекстЗапроса = " |SELECT | Substr(тзЗамены.СтароеЗначение,7,9) as [СтарыйЭлемент :Справочник.Клиенты], | СпрК.ID as [НовыйЭлемент :Справочник.Клиенты] |FROM | тзЗамены | INNER JOIN [Справочник.Клиенты] as СпрК | ON (тзЗамены.ИИН = СпрК.ИИН) AND | (Trim(СпрК.ИИН)<>'') | |"; ТекстЗапроса = " |SELECT | Substr(тзЗамены.СтароеЗначение,7,9) as [СтарыйЭлемент :Справочник.Клиенты], | СпрК.ID as [НовыйЭлемент :Справочник.Клиенты] |FROM | [Справочник.Клиенты] as СпрК | INNER JOIN тзЗамены | ON (тзЗамены.ИИН = СпрК.ИИН) AND | (Trim(СпрК.ИИН)<>'') AND | (СпрК.ismark <> '*') | |"; В справочнике около 100 000 записей в тз около 200-300 Отладочная информация Подбор индекса для таблицы SC14 : Ограничения: ISMARK ne; SP968[ИИН]=; Выбран индекс VI968: UPPER(SP968) Стоимость: 16 Подбор индекса для таблицы SC14 : Ограничения: ISMARK ne; Индекс не выбран. Стоимость: 74318 | |||
| 1
    
        ДенисЧ 21.01.21✎ 14:54 | 
        AND Trim(СпрК.ИИН)<>'')
 Забудь про индексы, скажи "превед" перебору таблицы | |||
| 2
    
        Volodja 21.01.21✎ 14:56 | 
        <> - Не использовать?     | |||
| 3
    
        ДенисЧ 21.01.21✎ 14:56 | 
        (2) Для начала Trim() )))
 Это же функция, чтобы её посчитать - нужно получить каждую строку таблицы... | |||
| 4
    
        Volodja 21.01.21✎ 14:57 | 
        Как тут тогда отсечь пустые?     | |||
| 5
    
        youalex 21.01.21✎ 15:00 | 
        а в склайте разве '' <> ' '? 
 или у тебя там не только пробелы могут быть ? | |||
| 6
    
        Volodja 21.01.21✎ 15:02 | 
        (5) этим я игнорирую пустые ИИН     | |||
| 7
    
        Volodja 21.01.21✎ 15:02 | 
        ИИН это 12-значная строка из цифр     | |||
| 8
    
        Volodja 21.01.21✎ 15:04 | 
        (3) Без Trim() также долго:
 (СпрК.ИИН<>' ') AND | |||
| 9
    
        Volodja 21.01.21✎ 15:05 | 
        Индекс по ИИН есть     | |||
| 10
    
        youalex 21.01.21✎ 15:10 | 
        А зачем тебе вообще это условие, 
 у тебя же INNER JOIN тзЗамены.ИИН = СпрК.ИИН т.е. ты можешь сначала в ТЗ отобрать элементы без пустого ИНН? | |||
| 11
    
        Volodja 21.01.21✎ 15:15 | 
        (10) Могу, конечно. Но почему это так долго работает?     | |||
| 12
    
        Ёпрст гуру 21.01.21✎ 15:16 | 
        (11) скан всей таблички жешь     | |||
| 13
    
        Volodja 21.01.21✎ 15:57 | 
        Сделал по совету (10). Отобрал предварительно все непустые ИИН.Заработало как надо.Быстро.
 Получается сканирование таблицы сильно зависит от размера строки? Это условие ведь осталось. хотя индекса нет СпрК.ismark <> '*' А в этом (СпрК.ИИН<>' ') ИИН = 12 символов и тормозит уже жутко | |||
| 14
    
        Sserj 21.01.21✎ 15:59 | 
        (11) На сколько помню Djelf писал что SQLite вообще ничего не знает об индексах 1С. То что в отладке говорится "подобрн" это уже вроде как сам движок 1С сообщает. А SQLite без информации об индексах план придумывает "от балды", в частности у тебя вот решил сначала выбрать все не помеченные на удаление а потом уже связать по ИНН.
 Помнится в таких случаях частенько приходилось разбивать на подзапросы, чтобы нужный индекс задействовать. Что-то типа такого: ТекстЗапроса = " |SELECT [СтарыйЭлемент :Справочник.Клиенты], [НовыйЭлемент :Справочник.Клиенты] |FROM ( |SELECT | Substr(тзЗамены.СтароеЗначение,7,9) as [СтарыйЭлемент :Справочник.Клиенты], | СпрК.ID as [НовыйЭлемент :Справочник.Клиенты], | Trim(СпрК.ismark) as [ПометкаУдаления] |FROM | [Справочник.Клиенты] as СпрК | INNER JOIN тзЗамены | ON (тзЗамены.ИИН = СпрК.ИИН) AND | (Trim(СпрК.ИИН)<>'') |) as T |WHERE NOT T.ПометкаУдаления = '*' | |"; | |||
| 15
    
        Volodja 21.01.21✎ 16:09 | 
        Ок.Спасибо всем. Буду теперь аккуратнее со строками.     | |||
| 16
    
        Djelf 21.01.21✎ 16:44 | 
        (14) Не совсем так. Про индексы движок то знает, но статистики индексов нет, и в случае с INNER JOIN может ошибиться в плане запроса и поменять выборку из таблиц местами.
 С LEFT JOIN такой проблемы нет, выборка из таблиц местами не меняется. Все становится более предсказуемо. Нужно смотреть план запроса через "explain QUERY PLAN "+ТекстЗапроса и более детально через "explain QUERY PLAN "+ТекстЗапроса. В данном запросе "ON (тзЗамены.ИИН = СпрК.ИИН) AND (Trim(СпрК.ИИН)<>'')" видимо должно быть 2 сканирования таблицы СпрК. Первое по индексу, второе - сырым чтением, потому что Trim(СпрК.ИИН) заблокирует выборку по индексу, потому что идет вычисление перед сравнением! А "сырое" чтение иногда оказывается быстрее, например: 
 | 
 
 | Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |