SlideShare una empresa de Scribd logo
1 de 84
Descargar para leer sin conexión
L’envers du décor
24 Octobre 2013
Apiness SA
Laurent Kohler

&

Nicolas Marfurt

www.apiness-software.ch
Le décor
Echange de données

Services Web
Echange de données

Services Web
Back-end Web
Gestion du contenu de l’application
(data model «business»)
Multilingue
Multi-utilisateurs
Gestion des autorisations
- par fonction
- sur la donnée

•
•

•

Web services de synchronisation
Application mobile
Outil d’affichage de données
Fonctionne également hors ligne
Structure et design simple
Synchronisation des données
- robuste
- performante
Effort de développement
Effort de développement
Effort de développement
Situation «typique»
Un client demande «une petite application
mobile multi-plateformes»
➡ aspect visuel et fonctionnel
➡ mais aussi développement important :
- back-end Web
- synchronisation
L’envers du décor
Options

Web server & Web services
Persistance données côté client mobile
- Modèle objet (Core Data)
- Modèle relationnel (SQLite natif)
- Autre (XML, JSON, plist...)
Contexte: back-end
Projet d’exemple Audio Guide

LAMP
CMS Joomla
Données «structurées», modèle relationnel
(MySQL)
Contexte: application iOS
Projet d’exemple Audio Guide

Modèle relationnel
Correspond au type de modèle du back-end

SQLite (sans Core Data)
Optimisation du SQL et des paramètres db
Modèle de données

Modèle «server» != modèle «app»
Exemples :

•

Serveur
-

•

Données multilingue
Gestion des autorisations

Application
-

Une langue sélectionnée
Au travail !
iOS - Cocoa
Options d’accès à SQLite
Options d’accès à SQLite
•

Utilisation de Core Data
Options d’accès à SQLite
•

Utilisation de Core Data
Options d’accès à SQLite
•

Utilisation de Core Data

•

Utilisation directe de la libraire SQLite native
➡

Fonctions C
Options d’accès à SQLite
•

Utilisation de Core Data

•

Utilisation directe de la libraire SQLite native
➡

•

Fonctions C

Wrapper ou framework existant
➡

FMDB
Options d’accès à SQLite
•

Utilisation de Core Data

•

Utilisation directe de la libraire SQLite native
➡

•

Wrapper ou framework existant
➡

•

Fonctions C

FMDB

Wrapper «maison»
Options d’accès à SQLite
•

Utilisation de Core Data

•

Utilisation directe de la libraire SQLite native
➡

•

Wrapper ou framework existant
➡

•

Fonctions C

FMDB

Wrapper «maison»

-

raison historique, plaisir d’explorer
mainmise sur le code (tests)
Architecture

APSSQLite
APSSQLiteObjectCoding
protocol

APSSQLiteDatabaseController

APSSQLiteDatabase

APSSQLiteRequest

SQLite

APSSQLiteObjectPersisting
protocol

APSSQLiteResultSet
Architecture

APSSQLite
APSSQLiteObjectCoding
protocol

APSSQLiteDatabaseController

APSSQLiteDatabase

APSSQLiteRequest

SQLite

APSSQLiteObjectPersisting
protocol

APSSQLiteResultSet
Architecture
MyProjectDatabaseController

APSSQLite
APSSQLiteObjectCoding
protocol

APSSQLiteDatabaseController

APSSQLiteDatabase

APSSQLiteRequest

SQLite

APSSQLiteObjectPersisting
protocol

APSSQLiteResultSet
Architecture
MyProjectDatabaseController

APSSQLite
APSSQLiteObjectCoding
protocol

APSSQLiteDatabaseController

APSSQLiteDatabase

APSSQLiteRequest

SQLite

APSSQLiteObjectPersisting
protocol

APSSQLiteResultSet
Architecture
MyProjectDatabaseController

MyClassResultSet

APSSQLiteDatabaseController

APSSQLiteObjectCoding
protocol

APSSQLite

APSSQLiteDatabase

APSSQLiteRequest

SQLite

APSSQLiteObjectPersisting
protocol

APSSQLiteResultSet
Architecture
MyProjectDatabaseController

MyClassResultSet

APSSQLiteDatabaseController

APSSQLiteObjectCoding
protocol

APSSQLite

APSSQLiteDatabase

APSSQLiteRequest

SQLite

APSSQLiteObjectPersisting
protocol

APSSQLiteResultSet
Architecture
MyProjectDatabaseController

MyClassResultSet

MyClass

APSSQLiteDatabaseController

APSSQLiteObjectCoding
protocol

APSSQLiteObjectPersisting
protocol

APSSQLite

APSSQLiteDatabase

APSSQLiteRequest

SQLite

APSSQLiteResultSet
Intégration
Modèle

MyClassResultSet

MyViewController
MyClass

MyProjectDatabaseController

Contrôleur

APSSQLite
Demo
Appel SQLite
APSSQLiteDatabase
- (BOOL)executeCUDRequest:(APSSQLiteRequest *)request error:(NSError *__autoreleasing *)error {
! BOOL success = YES;
!

sqlite3_stmt *statement;
int rc = sqlite3_prepare(self.db, [request.query UTF8String], -1, &statement, NULL);

!

if(rc == SQLITE_OK) {
rc = sqlite3_step(statement);

!

!

!
!
!
!

!
!
!
}
else {
*error = [[self class] errorWithCode:rc message:[NSString stringWithUTF8String:sqlite3_errmsg(self.db)]];
!
success = NO;
}

!
!
!
}

if(rc != SQLITE_DONE) {
*error = [[self class] errorWithCode:rc message:[NSString stringWithUTF8String:sqlite3_errmsg(self.db)]];
!
success = NO;
}
sqlite3_finalize(statement);

return success;
Appel SQLite
APSSQLiteDatabase
- (BOOL)executeCUDRequest:(APSSQLiteRequest *)request error:(NSError *__autoreleasing *)error {
! BOOL success = YES;
!

sqlite3_stmt *statement;
int rc = sqlite3_prepare(self.db, [request.query UTF8String], -1, &statement, NULL);

!

if(rc == SQLITE_OK) {
rc = sqlite3_step(statement);

!

!

!
!
!
!

!
!
!
}
else {
*error = [[self class] errorWithCode:rc message:[NSString stringWithUTF8String:sqlite3_errmsg(self.db)]];
!
success = NO;
}

!
!
!
}

if(rc != SQLITE_DONE) {
*error = [[self class] errorWithCode:rc message:[NSString stringWithUTF8String:sqlite3_errmsg(self.db)]];
!
success = NO;
}
sqlite3_finalize(statement);

return success;
Exécution d’une requête
TopicResultSet : APSSQLiteResultSet

+ (TopicResultSet *)fetchAll {
__block TopicResultSet *resultSet = nil;
[[GuideDatabaseController sharedDatabaseController] performBlockAndWait:^(APSSQLiteDatabase *database) {
NSString *query = @"SELECT * FROM audio_topic t WHERE t.isPublished = 1 ORDER BY t.sequence";
APSSQLiteRequest *request = [APSSQLiteRequest requestWithQuery:query];
request.resultClass = [TopicResultSet class];
NSError *error = nil;
resultSet = [database executeFetchRequest:request error:&error];
// Handle error...
}];
return resultSet;
}
Exécution d’une requête
TopicResultSet : APSSQLiteResultSet

+ (TopicResultSet *)fetchAll {
__block TopicResultSet *resultSet = nil;
[[GuideDatabaseController sharedDatabaseController] performBlockAndWait:^(APSSQLiteDatabase *database) {
NSString *query = @"SELECT * FROM audio_topic t WHERE t.isPublished = 1 ORDER BY t.sequence";
APSSQLiteRequest *request = [APSSQLiteRequest requestWithQuery:query];
request.resultClass = [TopicResultSet class];

}];
}

NSError *error = nil;
resultSet = [database executeFetchRequest:request error:&error];
// Handle error...

return resultSet;
Affichage des données
MyViewController : UITableViewController
@interface TopicListViewController ()
@property (strong, nonatomic) TopicResultSet *topicResultSet;
@end

- (void)viewDidLoad {
[super viewDidLoad];
}

self.topicResultSet = [TopicResultSet fetchAll];

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.topicResultSet count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TopicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TopicListViewControllerTopicCell];
NSDictionary *topic = self.topicResultSet[indexPath.row];
cell.textLabel.text = topic[TopicColumnTitle];
cell.detailTextLabel.text = topic[TopicColumnDescription];
}

return cell;
Affichage des données
MyViewController : UITableViewController
@interface TopicListViewController ()
@property (strong, nonatomic) TopicResultSet *topicResultSet;
@end

- (void)viewDidLoad {
[super viewDidLoad];
}

self.topicResultSet = [TopicResultSet fetchAll];

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.topicResultSet count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TopicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TopicListViewControllerTopicCell];

}

return cell;
Affichage des données
MyViewController : UITableViewController
@interface TopicListViewController ()
@property (strong, nonatomic) TopicResultSet *topicResultSet;
@end

- (void)viewDidLoad {
[super viewDidLoad];
}

self.topicResultSet = [TopicResultSet fetchAll];

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.topicResultSet count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TopicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TopicListViewControllerTopicCell];
Topic *topic = [self.topicResultSet topicForRowAtIndex:indexPath.row];
cell.textLabel.text = topic.title;
cell.detailTextLabel.text = topic.topicDescription;
}

return cell;
Base de données
Scénarios d’évolution des données

•

Mises à jour fréquentes mais en petit volume (news)
➡ Intégralité des données pas nécessaire

•
•

Mises à jour en masse (catalogue produit)
Installation en masse, mises à jour de petit volume (audio guide)
Contexte
Projet d’exemple Audio Guide

•

Installation de contenu type «audio guide musée»
- Texte, images, audio
- Création par volume de 100 à 1000 éléments environ
- Mise à jour sporadique et en petite quantité
Approches

•
•
•
•

Option 1 : «naïve» (la plus simple)
Option 2 : «typique SQLite» (transaction)
Option 3 : «insertion en masse»
Option 4 : «insertion en masse» + transaction
Contexte
2 tables relativement petites
- table parent : 12 colonnes (int, float, varchar)
- table détail : 7 colonnes (int, varchar), foreign key parent
Mesure
- nombre d’insertions par seconde
- données de référence : 1000 parents et 2000 détails
Option 1
Insertion ligne par ligne

FOR EACH ROW
EXEC:INSERT INTO TBL
(c1,c2...) SELECT 123,
‘abc’,...
Option 1
Insertion ligne par ligne

insertions /
sec

FOR EACH ROW
EXEC:INSERT INTO TBL
(c1,c2...) SELECT 123,
‘abc’,...
Option 1
Insertion ligne par ligne

insertions /
sec

FOR EACH ROW
EXEC:INSERT INTO TBL
(c1,c2...) SELECT 123,
‘abc’,...

Trop lent !
Option 2
Insertion ligne par ligne…
dans une transaction
BEGIN TRANSACTION
FOR EACH ROW
EXEC:INSERT INTO TBL
(c1,c2...) SELECT 123,
‘abc’,...
COMMIT (or rollback)
Option 2
Insertion ligne par ligne…
dans une transaction
BEGIN TRANSACTION
insertions /
sec

FOR EACH ROW
EXEC:INSERT INTO TBL
(c1,c2...) SELECT 123,
‘abc’,...
COMMIT (or rollback)
Option 2
Insertion ligne par ligne…
dans une transaction
BEGIN TRANSACTION
insertions /
sec

FOR EACH ROW
EXEC:INSERT INTO TBL
(c1,c2...) SELECT 123,
‘abc’,...
COMMIT (or rollback)

2.5x plus rapide !
Option 3
Insertion de plusieurs lignes en
une commande insert
EXEC:
INSERT
VALUES
(123,
,(345,
,(678,

INTO TBL (c1,c2)
‘Sqlite’)
‘Soft’)
‘Shake’);
Option 3
Insertion de plusieurs lignes en
une commande insert

SQLite ne connait pas insert many values !
(dépend des versions de SQLite…)

EXEC:
INSERT
VALUES
(123,
,(345,
,(678,

INTO TBL (c1,c2)
‘Sqlite’)
‘Soft’)
‘Shake’);
Option 3 - syntaxe SQLite
Insertion de plusieurs lignes en
une commande insert
EXEC:
INSERT INTO TBL (c1,c2)
SELECT 123, ‘Sqlite’
UNION SELECT 345, ‘Soft’
UNION SELECT 678, ‘Shake’;
Option 3 - syntaxe SQLite
Insertion de plusieurs lignes en
une commande insert

Limite SQLite :
au maximum 500 union select !

EXEC:
INSERT INTO TBL (c1,c2)
SELECT 123, ‘Sqlite’
UNION SELECT 345, ‘Soft’
UNION SELECT 678, ‘Shake’;
Option 3 - syntaxe SQLite
Insertion par paquets de 500
lignes
FOR EACH ROW
BUILD INSERT STATEMENT
WHEN «ENOUGH»
EXEC:
INSERT INTO TBL (c1,c2)
SELECT 123, ‘Sqlite’
UNION SELECT 345, ‘Soft’
UNION SELECT 678, ‘Shake’;
Option 3 - syntaxe SQLite
Insertion par paquets de 500
lignes

Code un peu plus
complexe

FOR EACH ROW
BUILD INSERT STATEMENT
WHEN «ENOUGH»
EXEC:
INSERT INTO TBL (c1,c2)
SELECT 123, ‘Sqlite’
UNION SELECT 345, ‘Soft’
UNION SELECT 678, ‘Shake’;
Option 4
Insertion par paquets de 500
lignes…
dans une transaction
BEGIN TRANSACTION
FOR EACH ROW
BUILD INSERT STATEMENT
WHEN «ENOUGH»
EXEC:
INSERT INTO TBL (c1,c2)
SELECT 123, ‘Sqlite’
UNION SELECT 345, ‘Soft’
UNION SELECT 678, ‘Shake’;
COMMIT (or rollback)
Option 4
Insertion par paquets de 500
lignes…
dans une transaction

Insertion «rapide»
de nombreuses lignes

BEGIN TRANSACTION
FOR EACH ROW
BUILD INSERT STATEMENT
WHEN «ENOUGH»
EXEC:
INSERT INTO TBL (c1,c2)
SELECT 123, ‘Sqlite’
UNION SELECT 345, ‘Soft’
UNION SELECT 678, ‘Shake’;
COMMIT (or rollback)
Comparaison des 4 options

insertions /
sec
Comparaison des 4 options

insertions /
sec

Option 4 45x plus rapide que l’option 1
1500 insertions / seconde sur iPad 3
600 insertions / seconde sur iPhone 4
Option 4
Insertion par paquets de 500
lignes…
dans une transaction

Performance satisfaisante dans le contexte
Au prix d’un code un peu plus complexe

Optio
adopt n
ée !

BEGIN TRANSACTION
FOR EACH ROW
BUILD INSERT STATEMENT
WHEN «ENOUGH»
EXEC:
INSERT INTO TBL (c1,c2)
SELECT 123, ‘Sqlite’
UNION SELECT 345, ‘Soft’
UNION SELECT 678, ‘Shake’;
COMMIT (or rollback)
Insert et Update
•

•

Coder «if exists update else insert»

•
•

Long à développer, long à exécuter
Update forcément itératif avec SQLite (1 by 1)

Approche SQLite efficace : INSERT OR REPLACE INTO...
➡ Si validation intégrité référentielle (foreign key)
Différer le contrôle au moment du commit :
PRAGMA defer_foreign_keys = ON

Optio
adopt n
ée !
Insert et Replace
•
•

Parfait pour des données provenant à 100% du serveur
Attention si certaines colonnes sont maintenues localement !

•

Le «insert or replace» modifie toutes les colonnes

➡ Option possible :
Utiliser un sub-select pour obtenir la valeur locale
Insert et Replace - exemple
EXEC:
INSERT INTO news (newsId, newsTitle,newsDesc, hasBeenRead)
SELECT
123
,‘SoftShake 2013’
,’24 et 25 octobre 2013’
,(SELECT hasBeenRead FROM news WHERE newsId = 123)
UNION SELECT ....
Insert et Replace - exemple
EXEC:
INSERT INTO news (newsId, newsTitle,newsDesc, hasBeenRead)
SELECT
123
,‘SoftShake 2013’
,’24 et 25 octobre 2013’
,(SELECT hasBeenRead FROM news WHERE newsId = 123)
UNION SELECT ....
work
aroun
d
30% p
lus le !
nt.
Insert et Replace - commentaires
•
•

Lorsque certaines colonnes sont maintenues localement
Data model :
- une table pour les données «serveur»
- une table pour les données «locale»
- une view pour accéder aux 2 facilement

•
•

Pas de perte de performance
Approche robuste

Optio
adopt n
ée !
Delete
•

Côté serveur
- «soft delete» (flag data inactive)

•

Côté application
- delete physique (à la fin de la synchronisation)
Réorganisation DB

•
•

SQLite est comparable aux autres base de données
Après de nombreux insert/update/delete, besoin de :
- Récupérer l’espace avec : VACUUM
Quand réorganiser ?
•
•
•

A l’ancienne; «une fois par semaine» ?
Souvent; après chaque synchro ?
Lorsque jugé nécessaire ?
- Evaluer les pages vides avec PRAGMA freelist_count
- Si «nombreuses» pages inutilisées : effectuer le «vacuum»
Quand réorganiser ?
•
•
•

A l’ancienne; «une fois par semaine» ?
Souvent; après chaque synchro ?
Lorsque jugé nécessaire ?
- Evaluer les pages vides avec PRAGMA freelist_count
- Si «nombreuses» pages inutilisées : effectuer le «vacuum»
vacuum est assez rapide
surtout s’il est effectué avant que la db soit totalement désorganisée
Important de le faire, «peu importe» quand !
Options SQLite
•
•

Journal mode

•

Mode «delete» par défaut

Attention au mode Write Ahead Log (WAL)

•
•

Meilleure concurrence d’accès
Meilleure performance «maintenant»...
- Car une partie du travail différée à plus tard !
- Sur device mobile, comportement potentiellement
ennuyeux
Pour conclure
•
•

SQLite est excellent et très performant !

•

Utiliser EXPLAIN pour analyser ce que fait SQLite

En définissant bien les indexes, pas de soucis de performance
du côté des select
Merci à vous tous pour votre attention !
No
SQL
?
Core Data ?

SQLite ?

Back-end
Web?

Discussion
BACKUP SLIDES
Backend web - gestion des données
Backend web - gestion des données
Outils existants (connus)

•

Contraintes par rapport au data model

•

(Très) rapide pour des fonctions simples

•

Risque d’atteindre une impasse

Développement «sur mesure»

•

trop long, trop coûteux
Gestion des données - nos choix
•

•

«middle-tier» commun qui génère le html en fonction de
paramètres et accès aux données par procédures stockées

•
•
•

Code PHP stable, on génère/écrit seulement le sql
Rapide
Optimisation des stored procedures toujours possible

Outil «maison» : JEdit

•

Développement par Apiness (Marc Perroulaz, L.Kohler)
Core Data - iOS 7 - Sqlite
•

Version SQLite

•
•

•

•

- iOS 6: version 3.7.13
- iOS 7.0: version 3.7.13

Options Core Data

•
•

Utilisation du mode WAL par défaut depuis iOS 7
Possibilité de passer des options SQLite à Core Data, entre autre le mode de journalisation:

•

@{ NSSQLitePragmasOption : @{@"journal_mode" : @"DELETE"} }

Trace Core Data (iOS 7 / sans analyse)

•
•
•
•

- pragma journal_mode=wal
- pragma cache_size=200
- pragma page_count
- pragma freelist_count

Más contenido relacionado

Destacado

Diagnosis y rehabilitación de unas terrazas
Diagnosis y rehabilitación de unas terrazasDiagnosis y rehabilitación de unas terrazas
Diagnosis y rehabilitación de unas terrazasDavid Roca
 
Presentacion Proyecto Regenera Limia
Presentacion Proyecto Regenera LimiaPresentacion Proyecto Regenera Limia
Presentacion Proyecto Regenera LimiaRegenera Limia
 
Tarea nº3 ime enfispo
Tarea nº3 ime enfispoTarea nº3 ime enfispo
Tarea nº3 ime enfispocayetanomanuel
 
Violentos Salidas Fumetas Y Borrachos
Violentos Salidas Fumetas Y BorrachosViolentos Salidas Fumetas Y Borrachos
Violentos Salidas Fumetas Y Borrachosguest6bc477
 
Hostess & promoter s.r.l. in store promotion
Hostess & promoter s.r.l.   in store promotionHostess & promoter s.r.l.   in store promotion
Hostess & promoter s.r.l. in store promotionDaniele Papa
 
Sealing Compounds for Power Stations in India
Sealing Compounds for Power Stations in IndiaSealing Compounds for Power Stations in India
Sealing Compounds for Power Stations in IndiaProject Sales Corp
 
Alameda Campestre
Alameda CampestreAlameda Campestre
Alameda Campestreromeroviedo
 
Life is a gift – live itift
Life is a gift – live itift  Life is a gift – live itift
Life is a gift – live itift ashish patil
 
1º a programa de educación vial 2013-2014
1º a programa de educación vial 2013-20141º a programa de educación vial 2013-2014
1º a programa de educación vial 2013-2014antoniniesta
 
Pulidora de probetas
Pulidora de probetasPulidora de probetas
Pulidora de probetasKevin Guzmán
 
Tecnica de imprecion en offset
Tecnica de imprecion en offsetTecnica de imprecion en offset
Tecnica de imprecion en offsetzuli02
 
Single Sign-On durch LDAP Anbindung an den Basler Schulen – Anforderung, Umfa...
Single Sign-On durch LDAP Anbindung an den Basler Schulen – Anforderung, Umfa...Single Sign-On durch LDAP Anbindung an den Basler Schulen – Anforderung, Umfa...
Single Sign-On durch LDAP Anbindung an den Basler Schulen – Anforderung, Umfa...Univention GmbH
 
Stihl catalogo promocoes
Stihl catalogo promocoesStihl catalogo promocoes
Stihl catalogo promocoessonia_marga
 
Historia de los premios oscar
Historia de los  premios oscarHistoria de los  premios oscar
Historia de los premios oscarTEAMRENTERIA
 

Destacado (20)

Revista Triodos nº 26
Revista Triodos nº 26Revista Triodos nº 26
Revista Triodos nº 26
 
Diagnosis y rehabilitación de unas terrazas
Diagnosis y rehabilitación de unas terrazasDiagnosis y rehabilitación de unas terrazas
Diagnosis y rehabilitación de unas terrazas
 
Presentacion Proyecto Regenera Limia
Presentacion Proyecto Regenera LimiaPresentacion Proyecto Regenera Limia
Presentacion Proyecto Regenera Limia
 
Tarea nº3 ime enfispo
Tarea nº3 ime enfispoTarea nº3 ime enfispo
Tarea nº3 ime enfispo
 
Violentos Salidas Fumetas Y Borrachos
Violentos Salidas Fumetas Y BorrachosViolentos Salidas Fumetas Y Borrachos
Violentos Salidas Fumetas Y Borrachos
 
Hostess & promoter s.r.l. in store promotion
Hostess & promoter s.r.l.   in store promotionHostess & promoter s.r.l.   in store promotion
Hostess & promoter s.r.l. in store promotion
 
Sealing Compounds for Power Stations in India
Sealing Compounds for Power Stations in IndiaSealing Compounds for Power Stations in India
Sealing Compounds for Power Stations in India
 
Landing pages
Landing pagesLanding pages
Landing pages
 
Alameda Campestre
Alameda CampestreAlameda Campestre
Alameda Campestre
 
Life is a gift – live itift
Life is a gift – live itift  Life is a gift – live itift
Life is a gift – live itift
 
Plan Evacuacion
Plan EvacuacionPlan Evacuacion
Plan Evacuacion
 
Trabajo de logica tu tu
Trabajo de logica tu tuTrabajo de logica tu tu
Trabajo de logica tu tu
 
1º a programa de educación vial 2013-2014
1º a programa de educación vial 2013-20141º a programa de educación vial 2013-2014
1º a programa de educación vial 2013-2014
 
Pulidora de probetas
Pulidora de probetasPulidora de probetas
Pulidora de probetas
 
Tecnica de imprecion en offset
Tecnica de imprecion en offsetTecnica de imprecion en offset
Tecnica de imprecion en offset
 
Single Sign-On durch LDAP Anbindung an den Basler Schulen – Anforderung, Umfa...
Single Sign-On durch LDAP Anbindung an den Basler Schulen – Anforderung, Umfa...Single Sign-On durch LDAP Anbindung an den Basler Schulen – Anforderung, Umfa...
Single Sign-On durch LDAP Anbindung an den Basler Schulen – Anforderung, Umfa...
 
Stihl catalogo promocoes
Stihl catalogo promocoesStihl catalogo promocoes
Stihl catalogo promocoes
 
Historia de los premios oscar
Historia de los  premios oscarHistoria de los  premios oscar
Historia de los premios oscar
 
Normas de laboratorio
Normas de laboratorioNormas de laboratorio
Normas de laboratorio
 
NutriPlan
NutriPlan NutriPlan
NutriPlan
 

Similar a Softshake apiness l'envers du décor

Activity
ActivityActivity
Activitydido
 
Découverte du moteur de rendu du projet Spartan
Découverte du moteur de rendu du projet SpartanDécouverte du moteur de rendu du projet Spartan
Découverte du moteur de rendu du projet SpartanMicrosoft
 
OWF12/HTML 5 local storage , olivier thomas, cto at webtyss
OWF12/HTML 5 local storage , olivier thomas, cto at webtyssOWF12/HTML 5 local storage , olivier thomas, cto at webtyss
OWF12/HTML 5 local storage , olivier thomas, cto at webtyssParis Open Source Summit
 
Procédures CLR pour SQL Server : avantages et inconvénients
Procédures CLR pour SQL Server : avantages et inconvénientsProcédures CLR pour SQL Server : avantages et inconvénients
Procédures CLR pour SQL Server : avantages et inconvénientsDenis Voituron
 
Web-In 2010: Programmation Native iOS (French)
Web-In 2010: Programmation Native iOS (French)Web-In 2010: Programmation Native iOS (French)
Web-In 2010: Programmation Native iOS (French)Fred Brunel
 
ASP.NET from Zero to Hero
ASP.NET from Zero to HeroASP.NET from Zero to Hero
ASP.NET from Zero to HeroCellenza
 
SSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQLSSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQLHervé Leclerc
 
Linq et Entity framework
Linq et Entity frameworkLinq et Entity framework
Linq et Entity frameworkDNG Consulting
 
NodeJS et SocketIO en mode scalable dans le Cloud - GAB 2015
NodeJS et SocketIO en mode scalable dans le Cloud - GAB 2015NodeJS et SocketIO en mode scalable dans le Cloud - GAB 2015
NodeJS et SocketIO en mode scalable dans le Cloud - GAB 2015Stéphane ESCANDELL
 
Collab365 - Office 365 API & PowerShell : Le meilleur des deux mondes!
Collab365 - Office 365 API & PowerShell : Le meilleur des deux mondes!Collab365 - Office 365 API & PowerShell : Le meilleur des deux mondes!
Collab365 - Office 365 API & PowerShell : Le meilleur des deux mondes!Sébastien Levert
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQLBruno Bonnin
 
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...MongoDB
 
Java Database Connectivity
Java Database ConnectivityJava Database Connectivity
Java Database ConnectivityKorteby Farouk
 
Digital GraphTour Paris - Neo4j 4.0, les nouveautés
Digital GraphTour Paris - Neo4j 4.0, les nouveautésDigital GraphTour Paris - Neo4j 4.0, les nouveautés
Digital GraphTour Paris - Neo4j 4.0, les nouveautésNeo4j
 
Play Framework - Toulouse JUG - nov 2011
Play Framework - Toulouse JUG - nov 2011Play Framework - Toulouse JUG - nov 2011
Play Framework - Toulouse JUG - nov 2011Sylvain Wallez
 
Quelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application webQuelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application web5pidou
 
ASP.NET Futures
ASP.NET FuturesASP.NET Futures
ASP.NET Futuresloicbar
 

Similar a Softshake apiness l'envers du décor (20)

Activity
ActivityActivity
Activity
 
Découverte du moteur de rendu du projet Spartan
Découverte du moteur de rendu du projet SpartanDécouverte du moteur de rendu du projet Spartan
Découverte du moteur de rendu du projet Spartan
 
OWF12/HTML 5 local storage , olivier thomas, cto at webtyss
OWF12/HTML 5 local storage , olivier thomas, cto at webtyssOWF12/HTML 5 local storage , olivier thomas, cto at webtyss
OWF12/HTML 5 local storage , olivier thomas, cto at webtyss
 
Procédures CLR pour SQL Server : avantages et inconvénients
Procédures CLR pour SQL Server : avantages et inconvénientsProcédures CLR pour SQL Server : avantages et inconvénients
Procédures CLR pour SQL Server : avantages et inconvénients
 
Web-In 2010: Programmation Native iOS (French)
Web-In 2010: Programmation Native iOS (French)Web-In 2010: Programmation Native iOS (French)
Web-In 2010: Programmation Native iOS (French)
 
ASP.NET from Zero to Hero
ASP.NET from Zero to HeroASP.NET from Zero to Hero
ASP.NET from Zero to Hero
 
nodejs vs vertx
nodejs vs vertxnodejs vs vertx
nodejs vs vertx
 
SSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQLSSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQL
 
Linq et Entity framework
Linq et Entity frameworkLinq et Entity framework
Linq et Entity framework
 
NodeJS et SocketIO en mode scalable dans le Cloud - GAB 2015
NodeJS et SocketIO en mode scalable dans le Cloud - GAB 2015NodeJS et SocketIO en mode scalable dans le Cloud - GAB 2015
NodeJS et SocketIO en mode scalable dans le Cloud - GAB 2015
 
3-android.pdf
3-android.pdf3-android.pdf
3-android.pdf
 
Collab365 - Office 365 API & PowerShell : Le meilleur des deux mondes!
Collab365 - Office 365 API & PowerShell : Le meilleur des deux mondes!Collab365 - Office 365 API & PowerShell : Le meilleur des deux mondes!
Collab365 - Office 365 API & PowerShell : Le meilleur des deux mondes!
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQL
 
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
 
Java Database Connectivity
Java Database ConnectivityJava Database Connectivity
Java Database Connectivity
 
HTML5
HTML5HTML5
HTML5
 
Digital GraphTour Paris - Neo4j 4.0, les nouveautés
Digital GraphTour Paris - Neo4j 4.0, les nouveautésDigital GraphTour Paris - Neo4j 4.0, les nouveautés
Digital GraphTour Paris - Neo4j 4.0, les nouveautés
 
Play Framework - Toulouse JUG - nov 2011
Play Framework - Toulouse JUG - nov 2011Play Framework - Toulouse JUG - nov 2011
Play Framework - Toulouse JUG - nov 2011
 
Quelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application webQuelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application web
 
ASP.NET Futures
ASP.NET FuturesASP.NET Futures
ASP.NET Futures
 

Softshake apiness l'envers du décor

  • 1. L’envers du décor 24 Octobre 2013
  • 2. Apiness SA Laurent Kohler & Nicolas Marfurt www.apiness-software.ch
  • 4.
  • 7. Back-end Web Gestion du contenu de l’application (data model «business») Multilingue Multi-utilisateurs Gestion des autorisations - par fonction - sur la donnée • • • Web services de synchronisation
  • 8. Application mobile Outil d’affichage de données Fonctionne également hors ligne Structure et design simple Synchronisation des données - robuste - performante
  • 9.
  • 10.
  • 14. Situation «typique» Un client demande «une petite application mobile multi-plateformes» ➡ aspect visuel et fonctionnel ➡ mais aussi développement important : - back-end Web - synchronisation
  • 16. Options Web server & Web services Persistance données côté client mobile - Modèle objet (Core Data) - Modèle relationnel (SQLite natif) - Autre (XML, JSON, plist...)
  • 17. Contexte: back-end Projet d’exemple Audio Guide LAMP CMS Joomla Données «structurées», modèle relationnel (MySQL)
  • 18. Contexte: application iOS Projet d’exemple Audio Guide Modèle relationnel Correspond au type de modèle du back-end SQLite (sans Core Data) Optimisation du SQL et des paramètres db
  • 19. Modèle de données Modèle «server» != modèle «app» Exemples : • Serveur - • Données multilingue Gestion des autorisations Application - Une langue sélectionnée
  • 23. Options d’accès à SQLite • Utilisation de Core Data
  • 24. Options d’accès à SQLite • Utilisation de Core Data
  • 25. Options d’accès à SQLite • Utilisation de Core Data • Utilisation directe de la libraire SQLite native ➡ Fonctions C
  • 26. Options d’accès à SQLite • Utilisation de Core Data • Utilisation directe de la libraire SQLite native ➡ • Fonctions C Wrapper ou framework existant ➡ FMDB
  • 27. Options d’accès à SQLite • Utilisation de Core Data • Utilisation directe de la libraire SQLite native ➡ • Wrapper ou framework existant ➡ • Fonctions C FMDB Wrapper «maison»
  • 28. Options d’accès à SQLite • Utilisation de Core Data • Utilisation directe de la libraire SQLite native ➡ • Wrapper ou framework existant ➡ • Fonctions C FMDB Wrapper «maison» - raison historique, plaisir d’explorer mainmise sur le code (tests)
  • 37. Demo
  • 38. Appel SQLite APSSQLiteDatabase - (BOOL)executeCUDRequest:(APSSQLiteRequest *)request error:(NSError *__autoreleasing *)error { ! BOOL success = YES; ! sqlite3_stmt *statement; int rc = sqlite3_prepare(self.db, [request.query UTF8String], -1, &statement, NULL); ! if(rc == SQLITE_OK) { rc = sqlite3_step(statement); ! ! ! ! ! ! ! ! ! } else { *error = [[self class] errorWithCode:rc message:[NSString stringWithUTF8String:sqlite3_errmsg(self.db)]]; ! success = NO; } ! ! ! } if(rc != SQLITE_DONE) { *error = [[self class] errorWithCode:rc message:[NSString stringWithUTF8String:sqlite3_errmsg(self.db)]]; ! success = NO; } sqlite3_finalize(statement); return success;
  • 39. Appel SQLite APSSQLiteDatabase - (BOOL)executeCUDRequest:(APSSQLiteRequest *)request error:(NSError *__autoreleasing *)error { ! BOOL success = YES; ! sqlite3_stmt *statement; int rc = sqlite3_prepare(self.db, [request.query UTF8String], -1, &statement, NULL); ! if(rc == SQLITE_OK) { rc = sqlite3_step(statement); ! ! ! ! ! ! ! ! ! } else { *error = [[self class] errorWithCode:rc message:[NSString stringWithUTF8String:sqlite3_errmsg(self.db)]]; ! success = NO; } ! ! ! } if(rc != SQLITE_DONE) { *error = [[self class] errorWithCode:rc message:[NSString stringWithUTF8String:sqlite3_errmsg(self.db)]]; ! success = NO; } sqlite3_finalize(statement); return success;
  • 40. Exécution d’une requête TopicResultSet : APSSQLiteResultSet + (TopicResultSet *)fetchAll { __block TopicResultSet *resultSet = nil; [[GuideDatabaseController sharedDatabaseController] performBlockAndWait:^(APSSQLiteDatabase *database) { NSString *query = @"SELECT * FROM audio_topic t WHERE t.isPublished = 1 ORDER BY t.sequence"; APSSQLiteRequest *request = [APSSQLiteRequest requestWithQuery:query]; request.resultClass = [TopicResultSet class]; NSError *error = nil; resultSet = [database executeFetchRequest:request error:&error]; // Handle error... }]; return resultSet; }
  • 41. Exécution d’une requête TopicResultSet : APSSQLiteResultSet + (TopicResultSet *)fetchAll { __block TopicResultSet *resultSet = nil; [[GuideDatabaseController sharedDatabaseController] performBlockAndWait:^(APSSQLiteDatabase *database) { NSString *query = @"SELECT * FROM audio_topic t WHERE t.isPublished = 1 ORDER BY t.sequence"; APSSQLiteRequest *request = [APSSQLiteRequest requestWithQuery:query]; request.resultClass = [TopicResultSet class]; }]; } NSError *error = nil; resultSet = [database executeFetchRequest:request error:&error]; // Handle error... return resultSet;
  • 42. Affichage des données MyViewController : UITableViewController @interface TopicListViewController () @property (strong, nonatomic) TopicResultSet *topicResultSet; @end - (void)viewDidLoad { [super viewDidLoad]; } self.topicResultSet = [TopicResultSet fetchAll]; - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.topicResultSet count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { TopicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TopicListViewControllerTopicCell]; NSDictionary *topic = self.topicResultSet[indexPath.row]; cell.textLabel.text = topic[TopicColumnTitle]; cell.detailTextLabel.text = topic[TopicColumnDescription]; } return cell;
  • 43. Affichage des données MyViewController : UITableViewController @interface TopicListViewController () @property (strong, nonatomic) TopicResultSet *topicResultSet; @end - (void)viewDidLoad { [super viewDidLoad]; } self.topicResultSet = [TopicResultSet fetchAll]; - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.topicResultSet count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { TopicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TopicListViewControllerTopicCell]; } return cell;
  • 44. Affichage des données MyViewController : UITableViewController @interface TopicListViewController () @property (strong, nonatomic) TopicResultSet *topicResultSet; @end - (void)viewDidLoad { [super viewDidLoad]; } self.topicResultSet = [TopicResultSet fetchAll]; - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.topicResultSet count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { TopicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TopicListViewControllerTopicCell]; Topic *topic = [self.topicResultSet topicForRowAtIndex:indexPath.row]; cell.textLabel.text = topic.title; cell.detailTextLabel.text = topic.topicDescription; } return cell;
  • 46. Scénarios d’évolution des données • Mises à jour fréquentes mais en petit volume (news) ➡ Intégralité des données pas nécessaire • • Mises à jour en masse (catalogue produit) Installation en masse, mises à jour de petit volume (audio guide)
  • 47. Contexte Projet d’exemple Audio Guide • Installation de contenu type «audio guide musée» - Texte, images, audio - Création par volume de 100 à 1000 éléments environ - Mise à jour sporadique et en petite quantité
  • 48. Approches • • • • Option 1 : «naïve» (la plus simple) Option 2 : «typique SQLite» (transaction) Option 3 : «insertion en masse» Option 4 : «insertion en masse» + transaction
  • 49. Contexte 2 tables relativement petites - table parent : 12 colonnes (int, float, varchar) - table détail : 7 colonnes (int, varchar), foreign key parent Mesure - nombre d’insertions par seconde - données de référence : 1000 parents et 2000 détails
  • 50. Option 1 Insertion ligne par ligne FOR EACH ROW EXEC:INSERT INTO TBL (c1,c2...) SELECT 123, ‘abc’,...
  • 51. Option 1 Insertion ligne par ligne insertions / sec FOR EACH ROW EXEC:INSERT INTO TBL (c1,c2...) SELECT 123, ‘abc’,...
  • 52. Option 1 Insertion ligne par ligne insertions / sec FOR EACH ROW EXEC:INSERT INTO TBL (c1,c2...) SELECT 123, ‘abc’,... Trop lent !
  • 53. Option 2 Insertion ligne par ligne… dans une transaction BEGIN TRANSACTION FOR EACH ROW EXEC:INSERT INTO TBL (c1,c2...) SELECT 123, ‘abc’,... COMMIT (or rollback)
  • 54. Option 2 Insertion ligne par ligne… dans une transaction BEGIN TRANSACTION insertions / sec FOR EACH ROW EXEC:INSERT INTO TBL (c1,c2...) SELECT 123, ‘abc’,... COMMIT (or rollback)
  • 55. Option 2 Insertion ligne par ligne… dans une transaction BEGIN TRANSACTION insertions / sec FOR EACH ROW EXEC:INSERT INTO TBL (c1,c2...) SELECT 123, ‘abc’,... COMMIT (or rollback) 2.5x plus rapide !
  • 56. Option 3 Insertion de plusieurs lignes en une commande insert EXEC: INSERT VALUES (123, ,(345, ,(678, INTO TBL (c1,c2) ‘Sqlite’) ‘Soft’) ‘Shake’);
  • 57. Option 3 Insertion de plusieurs lignes en une commande insert SQLite ne connait pas insert many values ! (dépend des versions de SQLite…) EXEC: INSERT VALUES (123, ,(345, ,(678, INTO TBL (c1,c2) ‘Sqlite’) ‘Soft’) ‘Shake’);
  • 58. Option 3 - syntaxe SQLite Insertion de plusieurs lignes en une commande insert EXEC: INSERT INTO TBL (c1,c2) SELECT 123, ‘Sqlite’ UNION SELECT 345, ‘Soft’ UNION SELECT 678, ‘Shake’;
  • 59. Option 3 - syntaxe SQLite Insertion de plusieurs lignes en une commande insert Limite SQLite : au maximum 500 union select ! EXEC: INSERT INTO TBL (c1,c2) SELECT 123, ‘Sqlite’ UNION SELECT 345, ‘Soft’ UNION SELECT 678, ‘Shake’;
  • 60. Option 3 - syntaxe SQLite Insertion par paquets de 500 lignes FOR EACH ROW BUILD INSERT STATEMENT WHEN «ENOUGH» EXEC: INSERT INTO TBL (c1,c2) SELECT 123, ‘Sqlite’ UNION SELECT 345, ‘Soft’ UNION SELECT 678, ‘Shake’;
  • 61. Option 3 - syntaxe SQLite Insertion par paquets de 500 lignes Code un peu plus complexe FOR EACH ROW BUILD INSERT STATEMENT WHEN «ENOUGH» EXEC: INSERT INTO TBL (c1,c2) SELECT 123, ‘Sqlite’ UNION SELECT 345, ‘Soft’ UNION SELECT 678, ‘Shake’;
  • 62. Option 4 Insertion par paquets de 500 lignes… dans une transaction BEGIN TRANSACTION FOR EACH ROW BUILD INSERT STATEMENT WHEN «ENOUGH» EXEC: INSERT INTO TBL (c1,c2) SELECT 123, ‘Sqlite’ UNION SELECT 345, ‘Soft’ UNION SELECT 678, ‘Shake’; COMMIT (or rollback)
  • 63. Option 4 Insertion par paquets de 500 lignes… dans une transaction Insertion «rapide» de nombreuses lignes BEGIN TRANSACTION FOR EACH ROW BUILD INSERT STATEMENT WHEN «ENOUGH» EXEC: INSERT INTO TBL (c1,c2) SELECT 123, ‘Sqlite’ UNION SELECT 345, ‘Soft’ UNION SELECT 678, ‘Shake’; COMMIT (or rollback)
  • 64. Comparaison des 4 options insertions / sec
  • 65. Comparaison des 4 options insertions / sec Option 4 45x plus rapide que l’option 1 1500 insertions / seconde sur iPad 3 600 insertions / seconde sur iPhone 4
  • 66. Option 4 Insertion par paquets de 500 lignes… dans une transaction Performance satisfaisante dans le contexte Au prix d’un code un peu plus complexe Optio adopt n ée ! BEGIN TRANSACTION FOR EACH ROW BUILD INSERT STATEMENT WHEN «ENOUGH» EXEC: INSERT INTO TBL (c1,c2) SELECT 123, ‘Sqlite’ UNION SELECT 345, ‘Soft’ UNION SELECT 678, ‘Shake’; COMMIT (or rollback)
  • 67. Insert et Update • • Coder «if exists update else insert» • • Long à développer, long à exécuter Update forcément itératif avec SQLite (1 by 1) Approche SQLite efficace : INSERT OR REPLACE INTO... ➡ Si validation intégrité référentielle (foreign key) Différer le contrôle au moment du commit : PRAGMA defer_foreign_keys = ON Optio adopt n ée !
  • 68. Insert et Replace • • Parfait pour des données provenant à 100% du serveur Attention si certaines colonnes sont maintenues localement ! • Le «insert or replace» modifie toutes les colonnes ➡ Option possible : Utiliser un sub-select pour obtenir la valeur locale
  • 69. Insert et Replace - exemple EXEC: INSERT INTO news (newsId, newsTitle,newsDesc, hasBeenRead) SELECT 123 ,‘SoftShake 2013’ ,’24 et 25 octobre 2013’ ,(SELECT hasBeenRead FROM news WHERE newsId = 123) UNION SELECT ....
  • 70. Insert et Replace - exemple EXEC: INSERT INTO news (newsId, newsTitle,newsDesc, hasBeenRead) SELECT 123 ,‘SoftShake 2013’ ,’24 et 25 octobre 2013’ ,(SELECT hasBeenRead FROM news WHERE newsId = 123) UNION SELECT .... work aroun d 30% p lus le ! nt.
  • 71. Insert et Replace - commentaires • • Lorsque certaines colonnes sont maintenues localement Data model : - une table pour les données «serveur» - une table pour les données «locale» - une view pour accéder aux 2 facilement • • Pas de perte de performance Approche robuste Optio adopt n ée !
  • 72. Delete • Côté serveur - «soft delete» (flag data inactive) • Côté application - delete physique (à la fin de la synchronisation)
  • 73. Réorganisation DB • • SQLite est comparable aux autres base de données Après de nombreux insert/update/delete, besoin de : - Récupérer l’espace avec : VACUUM
  • 74. Quand réorganiser ? • • • A l’ancienne; «une fois par semaine» ? Souvent; après chaque synchro ? Lorsque jugé nécessaire ? - Evaluer les pages vides avec PRAGMA freelist_count - Si «nombreuses» pages inutilisées : effectuer le «vacuum»
  • 75. Quand réorganiser ? • • • A l’ancienne; «une fois par semaine» ? Souvent; après chaque synchro ? Lorsque jugé nécessaire ? - Evaluer les pages vides avec PRAGMA freelist_count - Si «nombreuses» pages inutilisées : effectuer le «vacuum» vacuum est assez rapide surtout s’il est effectué avant que la db soit totalement désorganisée Important de le faire, «peu importe» quand !
  • 76. Options SQLite • • Journal mode • Mode «delete» par défaut Attention au mode Write Ahead Log (WAL) • • Meilleure concurrence d’accès Meilleure performance «maintenant»... - Car une partie du travail différée à plus tard ! - Sur device mobile, comportement potentiellement ennuyeux
  • 77. Pour conclure • • SQLite est excellent et très performant ! • Utiliser EXPLAIN pour analyser ce que fait SQLite En définissant bien les indexes, pas de soucis de performance du côté des select
  • 78. Merci à vous tous pour votre attention !
  • 79. No SQL ? Core Data ? SQLite ? Back-end Web? Discussion
  • 81. Backend web - gestion des données
  • 82. Backend web - gestion des données Outils existants (connus) • Contraintes par rapport au data model • (Très) rapide pour des fonctions simples • Risque d’atteindre une impasse Développement «sur mesure» • trop long, trop coûteux
  • 83. Gestion des données - nos choix • • «middle-tier» commun qui génère le html en fonction de paramètres et accès aux données par procédures stockées • • • Code PHP stable, on génère/écrit seulement le sql Rapide Optimisation des stored procedures toujours possible Outil «maison» : JEdit • Développement par Apiness (Marc Perroulaz, L.Kohler)
  • 84. Core Data - iOS 7 - Sqlite • Version SQLite • • • • - iOS 6: version 3.7.13 - iOS 7.0: version 3.7.13 Options Core Data • • Utilisation du mode WAL par défaut depuis iOS 7 Possibilité de passer des options SQLite à Core Data, entre autre le mode de journalisation: • @{ NSSQLitePragmasOption : @{@"journal_mode" : @"DELETE"} } Trace Core Data (iOS 7 / sans analyse) • • • • - pragma journal_mode=wal - pragma cache_size=200 - pragma page_count - pragma freelist_count