SlideShare une entreprise Scribd logo
1  sur  84
Télécharger pour lire hors ligne
L’envers du décor
24 Octobre 2013
Apiness SA
Laurent Kohler

&

Nicolas Marfurt

www.apiness-software.ch
Le décor
Softshake 2013 Apiness SA l'envers du 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
Softshake 2013 Apiness SA l'envers du décor
Softshake 2013 Apiness SA l'envers du décor
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

Contenu connexe

En vedette

Concert cançons tradicionals Joves cantans del Liceu Societat Ateneu 23 11 0...
Concert cançons tradicionals  Joves cantans del Liceu Societat Ateneu 23 11 0...Concert cançons tradicionals  Joves cantans del Liceu Societat Ateneu 23 11 0...
Concert cançons tradicionals Joves cantans del Liceu Societat Ateneu 23 11 0...zztopzz .
 
Stage mairie de vannes
Stage mairie de vannesStage mairie de vannes
Stage mairie de vannesmaximebaumard
 
Présentation jha dans les jv (vidéo)
Présentation jha dans les jv (vidéo)Présentation jha dans les jv (vidéo)
Présentation jha dans les jv (vidéo)jack-storm
 
Mystere trio 15 ans déjà ! Rétrospective
Mystere trio 15 ans déjà ! RétrospectiveMystere trio 15 ans déjà ! Rétrospective
Mystere trio 15 ans déjà ! RétrospectiveLaurent MEYER
 
Internet : comment passer du gratuit au payant
Internet : comment passer du gratuit au payantInternet : comment passer du gratuit au payant
Internet : comment passer du gratuit au payantLaurence Genty
 
Vive Les Blondes
Vive Les BlondesVive Les Blondes
Vive Les Blondeseric4274
 
Proyecto vida
Proyecto vidaProyecto vida
Proyecto vidakelin9
 
Pla de l'estany final
Pla de l'estany finalPla de l'estany final
Pla de l'estany finalbrahim365
 
Les droits humains dans les siècles et dans le monde
Les droits humains dans les siècles et dans le mondeLes droits humains dans les siècles et dans le monde
Les droits humains dans les siècles et dans le mondeAmnesty International France
 
Division de polinomios
Division  de polinomiosDivision  de polinomios
Division de polinomiosVictor Alegre
 
Communiqué de Presse Dentapass - PB Communication - Avril 2012
Communiqué de Presse Dentapass - PB Communication - Avril 2012Communiqué de Presse Dentapass - PB Communication - Avril 2012
Communiqué de Presse Dentapass - PB Communication - Avril 2012pbcom1998
 

En vedette (20)

Concert cançons tradicionals Joves cantans del Liceu Societat Ateneu 23 11 0...
Concert cançons tradicionals  Joves cantans del Liceu Societat Ateneu 23 11 0...Concert cançons tradicionals  Joves cantans del Liceu Societat Ateneu 23 11 0...
Concert cançons tradicionals Joves cantans del Liceu Societat Ateneu 23 11 0...
 
Stage mairie de vannes
Stage mairie de vannesStage mairie de vannes
Stage mairie de vannes
 
Présentation jha dans les jv (vidéo)
Présentation jha dans les jv (vidéo)Présentation jha dans les jv (vidéo)
Présentation jha dans les jv (vidéo)
 
Mystere trio 15 ans déjà ! Rétrospective
Mystere trio 15 ans déjà ! RétrospectiveMystere trio 15 ans déjà ! Rétrospective
Mystere trio 15 ans déjà ! Rétrospective
 
weasley
weasleyweasley
weasley
 
jeux: quelques pistes de travail...
jeux: quelques pistes de travail...jeux: quelques pistes de travail...
jeux: quelques pistes de travail...
 
Internet : comment passer du gratuit au payant
Internet : comment passer du gratuit au payantInternet : comment passer du gratuit au payant
Internet : comment passer du gratuit au payant
 
GBI
GBIGBI
GBI
 
Parler aux jeunes_de_la_torture
Parler aux jeunes_de_la_tortureParler aux jeunes_de_la_torture
Parler aux jeunes_de_la_torture
 
Tipos de conectores
Tipos de conectoresTipos de conectores
Tipos de conectores
 
Vive Les Blondes
Vive Les BlondesVive Les Blondes
Vive Les Blondes
 
Proyecto vida
Proyecto vidaProyecto vida
Proyecto vida
 
Pla de l'estany final
Pla de l'estany finalPla de l'estany final
Pla de l'estany final
 
Catalogo ropa
Catalogo ropaCatalogo ropa
Catalogo ropa
 
Les droits humains dans les siècles et dans le monde
Les droits humains dans les siècles et dans le mondeLes droits humains dans les siècles et dans le monde
Les droits humains dans les siècles et dans le monde
 
Sableoupierre
SableoupierreSableoupierre
Sableoupierre
 
Tics
TicsTics
Tics
 
Division de polinomios
Division  de polinomiosDivision  de polinomios
Division de polinomios
 
Tecnoparque agroecologico
Tecnoparque  agroecologicoTecnoparque  agroecologico
Tecnoparque agroecologico
 
Communiqué de Presse Dentapass - PB Communication - Avril 2012
Communiqué de Presse Dentapass - PB Communication - Avril 2012Communiqué de Presse Dentapass - PB Communication - Avril 2012
Communiqué de Presse Dentapass - PB Communication - Avril 2012
 

Similaire à Softshake 2013 Apiness SA 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
 

Similaire à Softshake 2013 Apiness SA 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
 

Dernier

Les Metiers de l'Intelligence Artificielle
Les Metiers de l'Intelligence ArtificielleLes Metiers de l'Intelligence Artificielle
Les Metiers de l'Intelligence ArtificielleErol GIRAUDY
 
The Importance of Indoor Air Quality (French)
The Importance of Indoor Air Quality (French)The Importance of Indoor Air Quality (French)
The Importance of Indoor Air Quality (French)IES VE
 
Workshop l'IA au service de l'industrie - Présentation générale - Extra 14...
Workshop l'IA au service de l'industrie - Présentation générale - Extra 14...Workshop l'IA au service de l'industrie - Présentation générale - Extra 14...
Workshop l'IA au service de l'industrie - Présentation générale - Extra 14...Infopole1
 
KIT-COPILOT and more Article du 20240311
KIT-COPILOT and more Article du 20240311KIT-COPILOT and more Article du 20240311
KIT-COPILOT and more Article du 20240311Erol GIRAUDY
 
Mes succès sur Microsoft LEARN et examens
Mes succès sur Microsoft LEARN et examensMes succès sur Microsoft LEARN et examens
Mes succès sur Microsoft LEARN et examensErol GIRAUDY
 
Installation de Sylius 2.0 et découverte du nouveau backoffice en Bootstrap
Installation de Sylius 2.0 et découverte du nouveau backoffice en BootstrapInstallation de Sylius 2.0 et découverte du nouveau backoffice en Bootstrap
Installation de Sylius 2.0 et découverte du nouveau backoffice en BootstrapMaxime Huran 🌈
 

Dernier (6)

Les Metiers de l'Intelligence Artificielle
Les Metiers de l'Intelligence ArtificielleLes Metiers de l'Intelligence Artificielle
Les Metiers de l'Intelligence Artificielle
 
The Importance of Indoor Air Quality (French)
The Importance of Indoor Air Quality (French)The Importance of Indoor Air Quality (French)
The Importance of Indoor Air Quality (French)
 
Workshop l'IA au service de l'industrie - Présentation générale - Extra 14...
Workshop l'IA au service de l'industrie - Présentation générale - Extra 14...Workshop l'IA au service de l'industrie - Présentation générale - Extra 14...
Workshop l'IA au service de l'industrie - Présentation générale - Extra 14...
 
KIT-COPILOT and more Article du 20240311
KIT-COPILOT and more Article du 20240311KIT-COPILOT and more Article du 20240311
KIT-COPILOT and more Article du 20240311
 
Mes succès sur Microsoft LEARN et examens
Mes succès sur Microsoft LEARN et examensMes succès sur Microsoft LEARN et examens
Mes succès sur Microsoft LEARN et examens
 
Installation de Sylius 2.0 et découverte du nouveau backoffice en Bootstrap
Installation de Sylius 2.0 et découverte du nouveau backoffice en BootstrapInstallation de Sylius 2.0 et découverte du nouveau backoffice en Bootstrap
Installation de Sylius 2.0 et découverte du nouveau backoffice en Bootstrap
 

Softshake 2013 Apiness SA 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
  • 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
  • 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