Comments 25
Из крайности в крайность. В андройде, тем не менее, есть общепринятый способ изоляции работы с БД через контент-провайдеры. Если использовать их и дружить с жизненным циклом андройда, то сами объекты сущностей часто оказываются не нужны — хватает курсора из базы и какого-нибудь интового уникального айдишника для адресации нужных данных
Наличие контент провайдера никак не влияет на то, что находится за ним — на схему ваших данны, то как организованы таблицы и связи между ними. Опять же дело вкуса, что использовать value object'ы или курсоры. Лично я предпочитаю в различных ListActivity'ях использовать курсоры, потому что они предоставляют все необходимое прямо из коробки. А в «обычных» экранах, которые отображают одну-две отдельные сущности value-object'ы.
Один из “побочных” эффектов такого подхода — падение производительности на операциях чтения, при достаточно сильной декомпозиции и нормализации, так как в запросах необходимо выполнять большее количество джойнов. И чем больше у вас записей в таблицах, тем дольше они выполняются.

большое количество джойнов ведёт не у ухудшению а, наоборот, к увеличению производительности. С диска-то меньше данных читается.
А то, что для join надо полностью прочесть как минимум поля, участвующие в нем это не считается? А то, глядишь, и вся таблица будет полностью считаться, особенности реализации sqllite лично я не знаю.
И процессорная обработка при этом накладывает свои ограничения — тоже мелочи.

Не говоря уже о том, что одним из принципов хорошо спроектированной базы данных считается наличие 0й записи, куда указывают при отсутствии ссылки.
Соответственно join ни как не может выступать условием, ограничивающим выборку и всегда идет полное объединение, запись к записи.
судя по написанному, вы даже примерно не представляете как работают современные движки баз данных (и SQLite встроенный в андроид в том числе).

Нет, для джойна поля не читаются либо читаются частично.

Про принципы проектирования с 0й записью — есть старые правила (вики) которые до сих пор никто улучшить не смог. Ни про какие 0е записи там ничего нет.
Да, как работают современные движки БД я имею мало представления.

С нормальными формами я знаком, но помимо нормальных форм есть еще, как бы их назвать, «лучшие практики» или «признаки хорошего вкуса», на Хабре статья проскакивала как-то (сейчас я ее что-то не найду).
Там одним из признаков было как раз наличие такой записи.

А если вернуться к тому, «что быстрее» — то в контексте автора было сказано, что 3я нормальная форма ограничивает производительность за счет необходимости большого числа джойнов.

Скажем, нам надо найти, кто живет на такой-то улице.
Быстрее будет сделать 4 джойна: Человек + Документ + Адрес + Улица.
Или если у нас сразу у человека есть ссылка на улицу: Человек + Улица.

Тут не идет речи, что джойн играет роль условия выборки. В этом случае да, скорость будет выше.
Тут идет речь, что нам не нужны промежуточные джойны за счет того, что мы отказались от строгого следования 3й нормальной форме.
И за счет уменьшения этих джойнов мы и выигрываем.
Да, как работают современные движки БД я имею мало представления.


после этого следует прекратить обсуждение. Представь что в таком же ключе будут обсуждать, скажем, стоматологию: «я сам не доктор но считаю что диаритовый бур позволяет сверлить зубы качественнее чем стальной».

Нет, вышеприведённые утверждения неверны. Движок базы данных использует изощрённую оптимизацию в результате которой данные могут вообще не читаться с диска.

Именно поэтому большое количество объединений таблиц ведён к экспоненциальному повышению производительности в большинстве случаев. А не наоборот, как это кажется непосвящённым.
Странная вера в движки.
Да, там и буферы, и хранение индексов отдельно от данных, и кеширование всего, что только можно. Но как минимум 1 раз считать все это придется. А учитывая ограничения платформы Android, то и сильно агрессивно все кешировать он не будет.
Да и чтение того же буфера — тоже чтение, пусть и быстрое. А это и обработка на ЦП и нагрузка на шины и т.д.

И пока нет ни одной причины, почему 4 джойна отработают быстрее 1, при условии одинаковый итоговых выборок (в общем случае, но такого поведения добиться можно, тут сложно спорить).
То, что join может ускорить операцию — я на спорю, он играет роль ограничивающего условия и может сильно нам снизить само количество считываемых данных.
Чем больше джойнов — тем сильнее данный эффект можно наблюдать.

Но если итоговая выборка одна и та же (скажем, считывается вся таблица, каждый объект джойнится с чем-то), то тут они только ограничат производительность.
Даже могу пример привести:
Пример, MS SQL
-- Один джойн
DECLARE @Begin datetime;
DECLARE @Count int;
DECLARE @End datetime; 

set @Begin = (select GETDATE());
set @Count = (select COUNT(1) from tablVisit
join tablMKAB on MKABID = tablVisit.rf_MKABID
where MKABID!=0 and tablVisit.rf_TAPID != 0)
set @End = (select GETDATE());

-- Два джойна
DECLARE @Begin2 datetime;
DECLARE @Count2 int;
DECLARE @End2 datetime; 
set @Begin2 = (select GETDATE());
set @Count2 = (select COUNT(1) from tablVisit
join tablTAP on TAPID = tablVisit.rf_TAPID
join tablMKAB on MKABID = tablTAP.rf_MKABID
where MKABID!=0 and tablVisit.rf_TAPID != 0)
set @End2 = (select GETDATE());

-- Результаты
select '1 join' as [Джойнов], @Count as [Результат], DATEPART(Ms, @End - @Begin) as [Время, ms]
union all
select '2 join' as [Джойнов], @Count2 as [Результат], DATEPART(Ms, @End2 - @Begin2) as [Время, ms]


Результат
Джойнов Результат   Время, ms
------- ----------- -----------
1 join  126446      60
2 join  126445      93

(2 row(s) affected)

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

В запросах стоит MKABID!=0 хотя в любом учебнике пишут что неравенство это неоптимизируемая операция и должна всегда исключаться.

На мой взгляд пример написан безграмотно и ничего кроме плохого владения предметом не демонстрирует. Нет смысла продолжать.
Есть ли пример приложения, в котором key-value подход повысил производительность?

Бины на Android лучше делать максимально простыми:
class Bean {
    public long id;
    public int number;
    public String title;
    // no getters & setters
}
UFO landed and left these words here
Автор, может я что-то упустил, но как в вашем случае выбрать данные по некому условию?
Он вроде пишет — считать в память всю группу и пробежаться через for. Оч удобно.
помогите развидеть мне ваш коммент обратно. что, если в группе 100500 элементов? а что, если мы хотим упорядочить их? или группировку сделать?
Я о том же — это не оч удобно, везде нужно будет писать кастомный метод. И медленно, если джава и если 100500 элементов.
Ну а если у нас хранятся сущности, размер которых при сериализации неизменен, то можно вообще использовать просто файл и обращаться к нашим данным через смещение. Ключи в данном случае(если их значения не могут быть сгенерированы по какому либо однозначному алгоритму) можно хранить в отдельной сущности в Map, в котором будет соответствие нашего ключа — смещению в файле. Более того, их можно «склеить» в один файл, учтя размеры при сериализации/десериализации.
По прочтении статьи у меня возник один вопрос — а зачем тогда нужна база данных вообще? Пишите в файл, в двоичном виде, всё подряд, и никаких проблем!
БД дает поиск по ключу.
Конечно, этого можно и своими силами добиться, но БД все-таки удобнее )
Точно, спасибо. Лучше не писать то, что уже кем-то написано
Не понял, причем тут Android. Есть задача, есть тип хранения который лучше всего подходит для ее решения. В вашей статье я вообще не увидел акцента на мобильной платформе.
Only those users with full accounts are able to leave comments. Log in, please.