|
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(СпрК.ИИН) заблокирует выборку по индексу, потому что идет вычисление перед сравнением! А "сырое" чтение иногда оказывается быстрее, например:
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |