Переключение на Главную Страницу Страницы: 1 ... 14 15 [16] 17 18 ... 79 ОтправитьПечать
Очень популярная тема (более 25 ответов) 1sqlite (число прочтений - 464521 )
Phoenix
Senior Member
****
Отсутствует


itpath.ru

Сообщений: 398
Местоположение: Москва
Зарегистрирован: 15. Июня 2006
Пол: Мужской
Re: 1sqlite
Ответ #225 - 09. Июля 2008 :: 07:59
Печать  
Саша, чей-то не смог запустить "Дерево документов" на СКЛ БД, это нормально?
ошибку могу привести.
  

Лень двигатель прогресса.&&http://www.itpath.ru&&;
Наверх
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: 1sqlite
Ответ #226 - 09. Июля 2008 :: 08:02
Печать  
Phoenix писал(а) 09. Июля 2008 :: 07:59:
Саша, чей-то не смог запустить "Дерево документов" на СКЛ БД, это нормально?
ошибку могу привести.

Это пример только для ДБФ-баз.
Для скл баз надо его переделывать под 1С++.
Вернее, надо скачать с этого же форума, когда-то я выкладывал вариант для 1С++ и скл-баз.
Ищи "Граф подчиненности документов"
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: 1sqlite
Ответ #227 - 09. Июля 2008 :: 08:17
Печать  
О, хотелось бы обратить ваше внимание на такую замечательную агрегатную функцию в SQLite, как group_concat.
Посмотрите в примере ТП со справочником товаров, как изящно получается строка с разбивкой остатков по складам.
Код
Выбрать все
запрОстатки.Подготовить("
|select
|	group_concat(rtrim(Склады.descr) || ': ' || Остатки.Кол, '; ') [Остаток]
|from
|(select
|	Склад,
|	sum(Количество) Кол
|from РегистрИтоги_ОстаткиТМЦ Итоги
|where period = :ДатаТА and Номенклатура = @goods
|group by Склад) Остатки
|left join Справочник_Склады Склады on Остатки.Склад = Склады.id
|");
....

запрОстатки.УстановитьПараметр("@goods", тп.ТекущаяСтрока);
стрИнфо = "Остатки по складам: " + запрОстатки.Выполнить(0);

 

  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: 1sqlite
Ответ #228 - 09. Июля 2008 :: 10:20
Печать  
Саша, а можно тогда уж еще небольшой ликбез.

Цитата:
--create table test(f1, f2, f3)
--create index on_test1 on test(f1)
--create index on_test2 on test(f2)
--create index on_test3 on test(f3)
--insert into test values(1, 1, 2)
--insert into test values(1, 2, 8)
--insert into test values(2, 1, 15)


Как эффективно строить выборки с участием нескольких индексов?

Цитата:
select * from test where f1 = 1 and f2 = 1 order by f3
select * from test where f1 = 1 or f2 = 1 order by f3
select * from test where f1 < 1 and f2 > 1 order by f3
select * from test where f1 < 1 or f2 > 1 order by f3


"or" надо переписывать как union?
А "and" и так нормально ляжет на индексы?
  

De quelle planète es-tu?
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: 1sqlite
Ответ #229 - 09. Июля 2008 :: 11:54
Печать  
kms писал(а) 09. Июля 2008 :: 10:20:
Саша, а можно тогда уж еще небольшой ликбез.

Цитата:
--create table test(f1, f2, f3)
--create index on_test1 on test(f1)
--create index on_test2 on test(f2)
--create index on_test3 on test(f3)
--insert into test values(1, 1, 2)
--insert into test values(1, 2, 8)
--insert into test values(2, 1, 15)


Как эффективно строить выборки с участием нескольких индексов?

Цитата:
select * from test where f1 = 1 and f2 = 1 order by f3
select * from test where f1 = 1 or f2 = 1 order by f3
select * from test where f1 < 1 and f2 > 1 order by f3
select * from test where f1 < 1 or f2 > 1 order by f3


"or" надо переписывать как union?
А "and" и так нормально ляжет на индексы?

Начнем с того, что SQLite, как и MSSQL делает проход по одной таблице ТОЛЬКО максимум по одному индексу.
То есть если хотим заюзать несколько индексов, то надо соотвественно, делать несколько подзапросов, организуя их так, чтобы в каждом подзапросе для таблицы участвовало только одно условие, попадающее в индекс.
И объединять результаты подзапросов через union, union all, intersect, и разные join
По порядку

запрос
Код
Выбрать все
select * from test where f1 = 1 and f2 = 1 order by f3
 


План выполнения:
Код
Выбрать все
Использование таблиц
order	from	detail
0	0	TABLE test WITH INDEX on_test2
 


Поэксперементировал и преобразовал:
Код
Выбрать все
select *
from test left join
(
   select rowid from test where f1 = 1
   intersect
   select rowid from test where f2 = 1
) tConstr on test.rowid = tConstr.rowid
where tConstr.rowid is not null
order by f3
 



План:
Код
Выбрать все
Использование таблиц
order	from	detail
0	0	TABLE test WITH INDEX on_test1
0	0	TABLE test WITH INDEX on_test2
0	0	TABLE test WITH INDEX on_test3 ORDER BY
1	1	TABLE  AS tConstr
 


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

Код
Выбрать все
select * from test where f1 = 1 or f2 = 1 order by f3
План:
Использование таблиц
order	from	detail
0	0	TABLE test WITH INDEX on_test3 ORDER BY
 



Переделываем
Код
Выбрать все
select *
from test left join
(
   select rowid from test where f1 = 1
   union
   select rowid from test where f2 = 1
) tConstr on test.rowid = tConstr.rowid
where tConstr.rowid is not null
order by f3
План:
Использование таблиц
order	from	detail
0	0	TABLE test WITH INDEX on_test1
0	0	TABLE test WITH INDEX on_test2
0	0	TABLE test WITH INDEX on_test3 ORDER BY
1	1	TABLE  AS tConstr
 



те принцип примерно понятен. and заменяем на intersect, or заменяем на union.
Для данных примеров пришлось извратится с запросом, чтобы попасть еще и в order by.
Если использовать inner join, SQLite почему-то идет не по on_test3, а по primary key (rowid), и сортирует во временной таблице.

Если бы в запросах не было order by f3, то было бы проще:
Код
Выбрать все
select * from test where f1 = 1 and f2 = 1
 


заменилось бы на

select * from test where f1 = 1
intersect
select * from test where f2 = 1

  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: 1sqlite
Ответ #230 - 09. Июля 2008 :: 12:12
Печать  
Также добавлю, что по слухам, таинственная Rushmore в Фоксе работает именно так.
Также на http://www.sqlite.org/cvstrac/wiki?p=PerformanceTuning пишут, что Postgree также сам оптимизирует выполнение по такому принципу.
  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: 1sqlite
Ответ #231 - 09. Июля 2008 :: 12:50
Печать  
orefkov писал(а) 09. Июля 2008 :: 07:54:
Кстати, для Кирюхи.
Таки нашел я оптимальный вариант запроса для SQLite, для выборки порции данных от ключа, если в индексе два и более полей.
Вот простой пример, из него все будет понятно:
Код
Выбрать все
--create table test(f1, f2, f3)
--create index on_test on test(f1, f2)
--insert into test values(1, 1, 2)
--insert into test values(1, 2, 8)
--insert into test values(2, 1, 15)

select * from (select * from test where f1 = 1 and f2>1 order by f1, f2) t
union all
select * from (select * from test where f1 > 1 order by f1, f2) t
limit 2
 


Генерится почти идеальный план.

Весьма остроумно Улыбка
***********
А что касается использования сразу 2-х индексов - это на мой взгляд весьма сомнительно.
Вместо одной выборки делается две.
Предположим - журнал документов с двумя индексами - "вид журнала" и второй - iddoc.
Отбор Вид="Реализация" и id='  123   '
Представляю, что получится, когда вместо  отбора по iddoc в запросе будут выбираться
все документы Реализации,  потом создаваться временная таблица, потом выбираться iddoc
а потом еще и intersect.

P.S>Кстати как  SQLLite делать подсказки, какой индекс использовать(оптимизировать ли выражение в where)?
Или не использовать ?
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: 1sqlite
Ответ #232 - 09. Июля 2008 :: 13:27
Печать  
kiruha писал(а) 09. Июля 2008 :: 12:50:
А что касается использования сразу 2-х индексов - это на мой взгляд весьма сомнительно.
Вместо одной выборки делается две.
Предположим - журнал документов с двумя индексами - "вид журнала" и второй - iddoc.
Отбор Вид="Реализация" и id='  123   '
Представляю, что получится, когда вместо  отбора по iddoc в запросе будут выбираться
все документы Реализации,  потом создаваться временная таблица, потом выбираться iddoc
а потом еще и intersect.


Когда я первый раз описывал эту технику, то сразу же оговорил, что применять ее следует с очень большой оглядкой, тщательно все взвесив. Применимо скорее всего для случаев, когда для обоих индексов средняя селективность.

Цитата:
P.S>Кстати как  SQLLite делать подсказки, какой индекс использовать(оптимизировать ли выражение в where)?
Или не использовать ?


Указать хинт, какой из индексов использовать при возможном выборе из нескольких - нельзя.
Для родных таблиц SQLite может помочь команда ANALYZE - строит статистику по индексам.
Зато можно ограничить количество выбираемых индексов с помощью значка '+' в условии перед именем поля, которое попадает в индекс, но не желательно к использованию.

Предположим - журнал документов с двумя индексами - "вид журнала" и второй - iddoc.
Отбор Вид="Реализация" и id='  123   '
Чтобы не заствлять SQLite мучительно думать, какой индекс выбрать (да еще и ошибится при этом), нужно написать
where +Вид='Реализация' and id='  123   '

Дело в том, что +Вид для SQLite уже не название колонки таблицы, а выражение. А для выражений он индексы не использует.
Модуль dbeng при выборе индексов выбирает тот, который закрывает больше условий. В данном случае, оба индекса закрывают по одному условию, но так как индекс по ID по списку раньше чем по виду журнала, выберется индекс по ID.
Также я хочу помимо количества закрываемых условий при использовании индекса учитывать еще и "процент заполненности".
Те индекс по iddoc - длина 1 поле, используется 100% индекса.
индекс по виду журнала - idjournal,date,time,iddoc - длина 4 поля, используется 25% индекса.
Нужно только формулу придумать, как оценить все вместе - и количество закрываемых условий, и их вид (=, >, <), и процент использованных полей из индекса, и попадание индекса в сортировку.
  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: 1sqlite
Ответ #233 - 09. Июля 2008 :: 13:53
Печать  
Про "+" очень полезно.
Жаль что автоматически нельзя - в принципе для ссылочных полей можно было бы
делать приблизительную оценку по количеству строк в таблице, к которой ссылка относится.
orefkov писал(а) 09. Июля 2008 :: 13:27:
...
Когда я первый раз описывал эту технику, то сразу же оговорил, что применять ее следует с очень большой оглядкой, тщательно все взвесив. Применимо скорее всего для случаев, когда для обоих индексов средняя селективность.


Ну предположим что в журнале есть еще поле и индекс "Контрагент"
10 000 строк в 1SJourn, 1000 строк на одного контрагента, 1000 строк на "Реализация"
в пересечении "Реализация"\"Контрагент" 100 строк.
Не вижу смысла, в чем выгода 2-х выборок и их соединения , когда можно
сделать 1-у выборку и потом отобрать у результирующего набора нужные строки - операция проще соединения -
один проход - итого на одну выборку меньше, не считая прочих затрат.
  
Наверх
 
IP записан
 
steban
1c++ developer
Отсутствует


#define sizeof(x) rand()

Сообщений: 787
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: 1sqlite
Ответ #234 - 09. Июля 2008 :: 17:14
Печать  
orefkov писал(а) 09. Июля 2008 :: 07:46:
Я совершенно не представляю, как автоматом из исходного текста запроса и названия ИдПоля сгенерить оптимальный запрос для получения ключа порядка по значению ИдПоля.
Может, при указании ИдПоля задавать еще и запрос для нахождения ключа по ИдПолю?

Можно ввести некоторые ограничения на текст запроса. Например, потребовать чтобы запрос был вида:
Код
Выбрать все
SELECT поля
FROM таблицы
[опционально соединения]
[опционально условия WHERE]
 


Запретить использовать HAVING, GROUP BY и т.п.
UNION и INTERSECT только в подзапросах.
При таких ограничениях вполне можно разобрать текст запроса при помощи PCRE
Готов помочь с PCRE.
только исходников с поставщиком на гугль-код нету
  

int getRandomNumber()&&{&&  return 4; //chosen by fair dice roll&&         //guaranteed to be random&&}
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: 1sqlite
Ответ #235 - 10. Июля 2008 :: 12:37
Печать  
steban писал(а) 09. Июля 2008 :: 17:14:
только исходников с поставщиком на гугль-код нету

Так что-то никто не отписывается, стал ли журнал нормально листаться, есть ли скачки по памяти при листании, справочник не зависает ли, обновление работает нормально или нет. Так что я пока не понимаю, коммитить или нет.
  
Наверх
 
IP записан
 
Chieftain
Senior Member
****
Отсутствует


___

Сообщений: 498
Местоположение: Тула
Зарегистрирован: 15. Февраля 2007
Пол: Мужской
Re: 1sqlite
Ответ #236 - 10. Июля 2008 :: 12:42
Печать  
orefkov писал(а) 10. Июля 2008 :: 12:37:
steban писал(а) 09. Июля 2008 :: 17:14:
только исходников с поставщиком на гугль-код нету

Так что-то никто не отписывается, стал ли журнал нормально листаться, есть ли скачки по памяти при листании, справочник не зависает ли, обновление работает нормально или нет. Так что я пока не понимаю, коммитить или нет.

По справочнику на первый взгляд все ОК.
Есть один вопрос - быстый поиск ты не подключал видимо?
  
Наверх
ICQ  
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: 1sqlite
Ответ #237 - 10. Июля 2008 :: 12:44
Печать  
Chieftain писал(а) 10. Июля 2008 :: 12:42:
orefkov писал(а) 10. Июля 2008 :: 12:37:
steban писал(а) 09. Июля 2008 :: 17:14:
только исходников с поставщиком на гугль-код нету

Так что-то никто не отписывается, стал ли журнал нормально листаться, есть ли скачки по памяти при листании, справочник не зависает ли, обновление работает нормально или нет. Так что я пока не понимаю, коммитить или нет.

По справочнику на первый взгляд все ОК.
Есть один вопрос - быстый поиск ты не подключал видимо?

Нет еще. Думаю над ним.
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: 1sqlite
Ответ #238 - 10. Июля 2008 :: 15:46
Печать  
orefkov писал(а) 10. Июля 2008 :: 12:37:
steban писал(а) 09. Июля 2008 :: 17:14:
только исходников с поставщиком на гугль-код нету

Так что-то никто не отписывается, стал ли журнал нормально листаться, есть ли скачки по памяти при листании, справочник не зависает ли, обновление работает нормально или нет. Так что я пока не понимаю, коммитить или нет.

Дык повода не было.
Все идеально, пока нечего сказать.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: 1sqlite
Ответ #239 - 10. Июля 2008 :: 17:01
Печать  
orefkov

Саша, а может быть получится сделать единый интерфейс выгрузки для большинства случаев?

ISQLiteResultLoader не универсален в силу использования sqlite3*, который в других задачах не нужен (да и сейчас не используется).
Плюс нет возможности ограничить количество строк.
И нет возможности для возврата ошибки.

Я вижу несколько по-другому:
Интерфейс1: построчный

* init
1. Источник спрашивает: приемник, у меня есть N колонок, X строк, принимаешь?
2. Приемник возвращает код/отсутствие ошибки; да, могу принять N1 колонок, X1 строк (N1 <= N, X1 <= X).

* setColumn (повторяется N1 раз)
3. Источник: добавляю колонку IDX, имя NAME, тип CType
4. Приемник: возвращает код ошибки

* addValues (повторяется X1 раз)
5. Источник: добавляю строку из N колонок, значения CValue**
6. Приемник: код ошибки

* getLastError()
предоставляется приемником после возврата кода ошибки.

виртуальный деструктор ИМХО не нужно включать в интрерфейс.
лучше AddRef() / Release().

CString не хотелось бы использовать.

Все функции имеют спецификацию throw()

Короче:
Код
Выбрать все
	ULONG AddRef();
	ULONG Release();

	// Подготовка приемника к приему результатов
	// Должен возвращать количество колонок, которое готов принять приемник.
	virtual HRESULT init(DWORD& colCount, DWORD& rowCount) = 0;

	// Добавление колонки в результат запроса
	virtual HRESULT setColumn(DWORD colIdx, LPCSTR colName, const CType& type) = 0;

	// Добавление строки в результат запроса.
	// Параметр - массив указателей на CValue, количеством равный количеству
	// добавленных колонок
	virtual HRESULT addValues(DWORD colCount, CValue** ppValues) = 0;
		количество колонок мне нужно, чтобы упростить реализацию интерфейса - Саша, думаю у тебя будут возражения, может быть я здесь и не прав

	// Присвоение возвращаемого значения
	virtual HRESULT assignRetValue(CValue& retVal) = 0;

		// Ошибка
		virtual LPCSTR getLastError() = 0;
 


« Последняя редакция: 10. Июля 2008 :: 18:11 - kms »  

De quelle planète es-tu?
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1 ... 14 15 [16] 17 18 ... 79
ОтправитьПечать