Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Обычная тема ДБФ Попасть в индекс по числовому полю (число прочтений - 3042 )
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
ДБФ Попасть в индекс по числовому полю
14. Мая 2008 :: 10:27
Печать  
Вопрос такой.
Как известно, в ДБФ-версии для индексирования numeric поля применяется выражение STR(поле, длина, точность).
К чему это приводит, тоже известно - идя по этому индексу, получаем, что  9 < -1 < 10
Как бы написать корректно выражение для правильного попадания в индекс по таким полям?
Например, в таблице есть записи:
SCXXX
--------
-3
-2
0
1
2
Мне надо выбрать по условию where SCXXX < 1
Если я напишу where STR(SCXXX, 5, 0) < '    1', то -3 и -2 пролетают, так как '-' > ' '
Как быть ?
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ДБФ Попасть в индекс по числовому полю
Ответ #1 - 14. Мая 2008 :: 11:22
Печать  
Причем со штатным 1С запросом интересная ситуация возникает:
Если пишу
Код
Выбрать все
|Товар = Справочник.Номенклатура.ТекущийЭлемент;
|Порядок = Справочник.Номенклатура.Порядок;
|Группировка Товар Без Групп Упорядочить по Товар.Порядок;
|Условие(Порядок < 1);
 


Так вот, элементы с отрицательным полем Порядок в результат попадают, но выводится в конце списка, те идет
0
0.5
0.9
-3
-4

Получается, для отбора записей с Порядок < 1 1С индексом не пользуется, а для упорядочивания по этому полю использует индекс.
  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: ДБФ Попасть в индекс по числовому полю
Ответ #2 - 14. Мая 2008 :: 12:11
Печать  
Да, индекс здесь неэффективен - отрицательные значения идут вперемежку
с положительными.
Можно только несколько условий OR типа
Код
Выбрать все
 OR   STR($СпрНом.Вес,8,3)+UPPER(СпрНом.DESCR) BETWEEN   '  -0.000' AND '  -9.999' 



В принципе разрядность до запятой вряд ли больше 10.
Да и то имеет смысл, если отрицательных в 10-100 и больше раз больше положительных.
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ДБФ Попасть в индекс по числовому полю
Ответ #3 - 14. Мая 2008 :: 12:35
Печать  
Это я все пытаюсь 1sqlite доделать, грамотную работу с индкесами.
Получается для примера так. Если есть индекс по полю numeric, то использовать его я могу только:
1. Если поле сравнивается на равенство. Здесь можно правильно выловить и положительные, и отрицательные числа.
2. Если поле сравнивается на неравенство, и в метаданных для него признак "Неотрицательное". Сравнение на больше-меньше работает правильно для положительных чисел.
3. Если поле не сравнивается, а просто используется для упорядочивания. Здесь я получу такое же поведение, как в 1С, то есть хуже чем было не станет.

Вот примерно так.
  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: ДБФ Попасть в индекс по числовому полю
Ответ #4 - 14. Мая 2008 :: 12:40
Печать  
orefkov писал(а) 14. Мая 2008 :: 12:35:
Это я все пытаюсь 1sqlite доделать, грамотную работу с индкесами.
Получается для примера так. Если есть индекс по полю numeric, то использовать его я могу только:
1. Если поле сравнивается на равенство. Здесь можно правильно выловить и положительные, и отрицательные числа.
2. Если поле сравнивается на неравенство, и в метаданных для него признак "Неотрицательное". Сравнение на больше-меньше работает правильно для положительных чисел.
3. Если поле не сравнивается, а просто используется для упорядочивания. Здесь я получу такое же поведение, как в 1С, то есть хуже чем было не станет.

Вот примерно так.


4. Если поле сравнивается на неравенство, и в метаданных для него отсутствует признак "Неотрицательное"
А подстроить условие OR не получится разве под размерность, если уж используются метаданные?

А как в sqllite будет решена проблема JOIN и группирования - хотя бы как в Индексированной таблице(без полного перебора) - лично для меня основной недостаток
  
Наверх
 
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: ДБФ Попасть в индекс по числовому полю
Ответ #5 - 15. Мая 2008 :: 05:17
Печать  
kiruha писал(а) 14. Мая 2008 :: 12:40:
А как в sqllite будет решена проблема JOIN и группирования - хотя бы как в Индексированной таблице(без полного перебора) - лично для меня основной недостаток

Может уже пофиксили ошибку вот ссылки
http://www.sqlite.org/releaselog/3_5_9.html
http://www.sqlite.org/cvstrac/tktview?tn=3015

Хорошо бы пересобрать sqlite с текущей версией ( 3.5.9 ) и все заново проверить.
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ДБФ Попасть в индекс по числовому полю
Ответ #6 - 15. Мая 2008 :: 05:21
Печать  
kiruha писал(а) 14. Мая 2008 :: 12:40:
4. Если поле сравнивается на неравенство, и в метаданных для него отсутствует признак "Неотрицательное"
А подстроить условие OR не получится разве под размерность, если уж используются метаданные?

Каким образом не совсем понял.
Вот для примера, поле numeric(5,0). Нужно выбрать все, меньшее 1.
Как разбить на несколько OR ?
А допустим, выбрать все меньше -3?
Тоже не совсем понятно.

kiruha писал(а) 14. Мая 2008 :: 12:40:
А как в sqllite будет решена проблема JOIN и группирования - хотя бы как в Индексированной таблице(без полного перебора) - лично для меня основной недостаток

А какие проблемы с JOIN и группировками?
Если в индекс попадаешь, никаких особых проблем вроде нет.
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ДБФ Попасть в индекс по числовому полю
Ответ #7 - 15. Мая 2008 :: 05:27
Печать  
Z1 писал(а) 15. Мая 2008 :: 05:17:
kiruha писал(а) 14. Мая 2008 :: 12:40:
А как в sqllite будет решена проблема JOIN и группирования - хотя бы как в Индексированной таблице(без полного перебора) - лично для меня основной недостаток

Может уже пофиксили ошибку вот ссылки
http://www.sqlite.org/releaselog/3_5_9.html
http://www.sqlite.org/cvstrac/tktview?tn=3015

Хорошо бы пересобрать sqlite с текущей версией ( 3.5.9 ) и все заново проверить.

О, как раз ждал 3.5.9
Заюзал 3.5.8, а в ней LEFT JOIN индекс не юзает.
  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: ДБФ Попасть в индекс по числовому полю
Ответ #8 - 15. Мая 2008 :: 08:58
Печать  
orefkov писал(а) 15. Мая 2008 :: 05:21:
Каким образом не совсем понял.
Вот для примера, поле numeric(5,0). Нужно выбрать все, меньшее 1.
Как разбить на несколько OR ?
А допустим, выбрать все меньше -3?



Для -3
Код
Выбрать все
(STR($СпрНом.Вес,5,0) BETWEEN   '   -3' AND '   -9' )
 OR(STR($СпрНом.Вес,5,0) BETWEEN   '  -10' AND '  -99' )
 OR(STR($СпрНом.Вес,5,0) BETWEEN   ' -100' AND '  -999' )
 OR(STR($СпрНом.Вес,5,0) BETWEEN   '-1000' AND ' -9999' )
 



Проблема в join была в производительности Join и group на больших объемах данных(например две
таблицы соединяются по полю не входящему в индекс) -
из за последовательного перебора время с ростом объема таблиц росло экспоненциально.
В Fox же использовалось предварительное индексирование.

Может действительно в новом релизе поправили  Улыбка
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ДБФ Попасть в индекс по числовому полю
Ответ #9 - 15. Мая 2008 :: 11:54
Печать  
kiruha писал(а) 15. Мая 2008 :: 08:58:
Для -3
Код
Выбрать все
(STR($СпрНом.Вес,5,0) BETWEEN   '   -3' AND '   -9' )
 OR(STR($СпрНом.Вес,5,0) BETWEEN   '  -10' AND '  -99' )
 OR(STR($СпрНом.Вес,5,0) BETWEEN   ' -100' AND '  -999' )
 OR(STR($СпрНом.Вес,5,0) BETWEEN   '-1000' AND ' -9999' )
 



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

kiruha писал(а) 15. Мая 2008 :: 08:58:
Проблема в join была в производительности Join и group на больших объемах данных(например две
таблицы соединяются по полю не входящему в индекс) -
из за последовательного перебора время с ростом объема таблиц росло экспоненциально.
В Fox же использовалось предварительное индексирование.

Ну, этого там нет, и вряд ли будет. Если индекса по ведомой таблице нет по полю соединения, он будет для каждой строки ведущей таблицы перебирать все строки ведомой, то есть время будет пропорционально произведению количества строк ведущей и ведомой таблицы. Сейчас можно обойти так:
Код
Выбрать все
create temp table t1 as select from Таблица.НеИндексированноеПоле, Таблица.id
create index t1_ on t1(НеИндексированноеПоле)
select ... from ВедущаяТаблица
    inner join t1 on ВедущаяТаблица.поле = t1.НеИндексированноеПоле
inner join Таблица on t1.id = Таблица.id
 


А в будущем я попробую это тоже спрятать от SQLite, и если он будет хотеть от меня выборку по неиндексируемому полю, создавать временный индекс на-лету.
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать