Hi Ralf,
1. I did not try to use something else than Collection.
2. the load behavior doesn't change if I remove the depends at
Habilitation.profile. In fact I've removed it.
3. Here are the get/set/add methods for listHabilitation :
public java.util.Collection getListeHabilitation() {
return listeHabilitation;
}
public void setListeHabilitation(java.util.Collection collection) {
listeHabilitation = collection;
}
public void addHabilitation(Habilitation habilitation) {
listeHabilitation.add(habilitation);
}
The mesthods setListeHabilitation and getListeHabilitation are used by
castor.
4. When I'm loading the Profile with its Habilitations I need
sometime a write access (to update this Profil), and more often I should
need only readonly access.
5. castor is the only application that access this tables.
6. Now I have put a cache-type for the 2 classes :
<class name="test.testCollection.Profil" access="shared"
key-generator="MAX" identity="idProfil">
<cache-type type="count-limited" capacity="100" />
<class name="test.testCollection.Habilitation" access="shared"
key-generator="MAX" identity="idHabilitation">
<cache-type type="count-limited" capacity="2000" />
The default seems to be
<cache-type type="count-limited" capacity="30" />
Thanks for your help.
Sylvie.
The Oql query is :
OQL_LES_PROFILS = "SELECT profil FROM test.testCollection.Profil profil
WHERE organisme= $1 and mnemonique= $2 order by organisme, mnemonique,
numVersion DESC";
Here's what happens in mysql log :
050607 8:23:24 1 Query show status
050607 8:23:34 1 Query show status
55 Connect [EMAIL PROTECTED] on scapin_rf_innodb
55 Init DB scapin_rf_innodb
55 Query select round('inf'), round('-inf'),
round('nan')
55 Query SHOW VARIABLES
55 Query SET autocommit=1
55 Query SET autocommit=0
55 Query SELECT
SCA_PROFIL.PRO_ID,SCA_PROFIL.PRO_ORGANISME,SCA_PROFIL.PRO_NOM_PROFIL,SCA_PRO
FIL.PRO_NUM_VERSION,SCA_PROFIL.PRO_RESUME,SCA_PROFIL.PRO_DESCRIPTION,SCA_PRO
FIL.PRO_ORGANISME_PERE,SCA_PROFIL.PRO_NOM_PROFIL_PERE,SCA_PROF_HABILITATION.
HAB_ID FROM SCA_PROFIL LEFT OUTER JOIN SCA_PROF_HABILITATION ON
SCA_PROFIL.PRO_ID=SCA_PROF_HABILITATION.PRO_ID WHERE
(SCA_PROFIL.PRO_ORGANISME = 'National' and SCA_PROFIL.PRO_NOM_PROFIL =
'Technicien') ORDER BY SCA_PROFIL.PRO_ORGANISME , SCA_PROFIL.PRO_NOM_PROFIL
, SCA_PROFIL.PRO_NUM_VERSION DESC
050607 8:23:35 55 Query SELECT
SCA_PROF_HABILITATION.PRO_ID,SCA_PROF_HABILITATION.HAB_ACTION,SCA_PROF_HABIL
ITATION.HAB_DROIT FROM SCA_PROF_HABILITATION WHERE
SCA_PROF_HABILITATION.HAB_ID=1
55 Query SELECT
SCA_PROF_HABILITATION.PRO_ID,SCA_PROF_HABILITATION.HAB_ACTION,SCA_PROF_HABIL
ITATION.HAB_DROIT FROM SCA_PROF_HABILITATION WHERE
SCA_PROF_HABILITATION.HAB_ID=2
55 Query SELECT
SCA_PROF_HABILITATION.PRO_ID,SCA_PROF_HABILITATION.HAB_ACTION,SCA_PROF_HABIL
ITATION.HAB_DROIT FROM SCA_PROF_HABILITATION WHERE
SCA_PROF_HABILITATION.HAB_ID=3
55 Query SELECT
SCA_PROF_HABILITATION.PRO_ID,SCA_PROF_HABILITATION.HAB_ACTION,SCA_PROF_HABIL
ITATION.HAB_DROIT FROM SCA_PROF_HABILITATION WHERE
SCA_PROF_HABILITATION.HAB_ID=4
.
.
.
Here is a test case to reproduce easily the "problem".
Mapping file :
<?xml version="1.0" ?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.exolab.org/mapping.dtd">
<mapping>
<class name="test.testCollection.Profil" access="shared"
key-generator="MAX" identity="idProfil">
<cache-type type="count-limited" capacity="100" />
<map-to table="SCA_PROFIL" />
<field name="idProfil" type="integer" required="true">
<sql type="integer" name="PRO_ID" />
<bind-xml name="idProfil" />
</field>
<field name="organisme" type="string">
<sql type="char" name="PRO_ORGANISME" />
<bind-xml name="organisme" />
</field>
<field name="mnemonique" type="string">
<sql type="char" name="PRO_NOM_PROFIL" />
<bind-xml name="mnemonique" />
</field>
<field name="numVersion" type="integer">
<sql type="integer" name="PRO_NUM_VERSION" />
<bind-xml name="numVersion" />
</field>
<field name="resume" type="string">
<sql type="char" name="PRO_RESUME" />
<bind-xml name="resume" />
</field>
<field name="description" type="string">
<sql type="char" name="PRO_DESCRIPTION" />
<bind-xml name="description" />
</field>
<field name="organismePere" type="string">
<sql type="char" name="PRO_ORGANISME_PERE" />
<bind-xml name="organismePere" />
</field>
<field name="nomProfilPere" type="string">
<sql type="char" name="PRO_NOM_PROFIL_PERE" />
<bind-xml name="nomProfilPere" />
</field>
<field name="listeHabilitation" collection="collection" lazy="true"
type="test.testCollection.Habilitation">
<sql many-key="PRO_ID" />
<bind-xml name="listeHabilitation" />
</field>
</class>
<class name="test.testCollection.Habilitation" access="shared"
key-generator="MAX" identity="idHabilitation">
<cache-type type="count-limited" capacity="2000" />
<map-to table="SCA_PROF_HABILITATION" />
<field name="idHabilitation" type="integer" required="true">
<sql type="integer" name="HAB_ID" />
<bind-xml name="idHabilitation" />
</field>
<field name="profil" type="test.testCollection.Profil">
<sql name="PRO_ID" />
<bind-xml name="profil" />
</field>
<field name="action" type="string">
<sql type="char" name="HAB_ACTION" />
<bind-xml name="action" />
</field>
<field name="droitAssocie" type="string">
<sql type="char" name="HAB_DROIT" />
<bind-xml name="droitAssocie" />
</field>
</class>
</mapping>
package test.testCollection;
import fr.cnam.scapin.util.FormatUtils;
public class Profil {
private int idProfil;
private String organisme;
private String mnemonique;
private int numVersion;
private String resume;
private String description;
private String organismePere;
private String nomProfilPere;
private java.util.Collection listeHabilitation;
public Profil() {
}
public String getMnemonique() {
return mnemonique;
}
public void addHabilitation(Habilitation habilitation) {
listeHabilitation.add(habilitation);
}
public String getDescription() {
return description;
}
public int getIdProfil() {
return idProfil;
}
public java.util.Collection getListeHabilitation() {
return listeHabilitation;
}
public String getNomProfilPere() {
return nomProfilPere;
}
public int getNumVersion() {
return numVersion;
}
public String getOrganisme() {
return organisme;
}
public String getOrganismePere() {
return organismePere;
}
public String getResume() {
return resume;
}
public void setDescription(String string) {
description = FormatUtils.nullString(string);
}
public void setIdProfil(int i) {
idProfil = i;
}
public void setListeHabilitation(java.util.Collection collection) {
listeHabilitation = collection;
}
public void setMnemonique(String string) {
mnemonique = FormatUtils.nullString(string);
}
public void setNomProfilPere(String string) {
nomProfilPere = FormatUtils.nullString(string);
}
public void setNumVersion(int i) {
numVersion = i;
}
public void setOrganisme(String string) {
organisme = FormatUtils.nullString(string);
}
public void setOrganismePere(String string) {
organismePere = FormatUtils.nullString(string);
}
public void setResume(String string) {
resume = FormatUtils.nullString(string);
}
}
package test.testCollection;
import fr.cnam.scapin.util.FormatUtils;
public class Habilitation {
private int idHabilitation;
private Profil profil;
private String action;
private String droitAssocie;
public Habilitation() {
}
public String getAction() {
return action;
}
public String getDroitAssocie() {
return droitAssocie;
}
public int getIdHabilitation() {
return idHabilitation;
}
public Profil getProfil() {
return profil;
}
public void setAction(String string) {
action = FormatUtils.nullString(string);
}
public void setDroitAssocie(String string) {
droitAssocie = FormatUtils.nullString(string);
}
public void setIdHabilitation(int i) {
idHabilitation = i;
}
public void setProfil(Profil profil) {
this.profil = profil;
}
}
package test.testCollection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import junit.framework.TestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.JDO;
import org.exolab.castor.jdo.OQLQuery;
import org.exolab.castor.jdo.QueryResults;
import org.exolab.castor.util.JdoConfFactory;
public class TestCollection extends TestCase {
private static Log log = null;
// private JDO2 jdo;
private JDO jdo = null;
private static final String DATABASE_NAME = "toto";
public static final String databaseFile = "jdo_conf.xml";
private static final String OQL_LES_PROFILS = "SELECT profil FROM
test.testCollection.Profil profil WHERE organisme= $1 and mnemonique= $2
order by organisme, mnemonique, numVersion DESC";
/**
* Creates an instance of this class.
* @param name Name of the test case.
*/
public TestCollection(String name) {
super(name);
}
/*
* @see TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
log =
LogFactory.getFactory().getInstance(TestCollection.class);
if (jdo == null) {
URL u = this.getClass().getResource(databaseFile);
(databaseFile).toString(), getClass().getClassLoader());
org.exolab.castor.jdo.conf.Database jdoDbConf;
String db_url =
"jdbc:mysql://localhost/scapin_rf_innodb";
String username = "root";
String password = "";
// Use the mapping file located in the current
Java package
URL map_url =
getClass().getResource("mapping.xml");
// Create the JDO object
jdo = new JDO();
jdo.setDatabaseName("toto");
// Set up the JDO configuration with the specified
database driver and connection information
jdoDbConf = JdoConfFactory.createJdoDbConf("toto",
"mysql",
JdoConfFactory.createJdoDriverConf("org.gjt.mm.mysql.Driver",
db_url, username, password));
// Store the mapping file location in the
configuration
jdoDbConf.addMapping(JdoConfFactory.createJdoMappingConf(map_url.toString())
);
// Activate the JDO configuration
jdo.setConfiguration(JdoConfFactory.createJdoConf(jdoDbConf));
if (jdo == null) {
log.error("error.initAccesBaseDeDonnees.erreur" + "\nBase " + DATABASE_NAME
+ " - " + "Objet JDO introuvable ( databaseFileConfig = " + databaseFile + "
- nomDatabase = " + DATABASE_NAME + ")");
} else {
log.info("jdo = " + jdo);
}
}
}
/*
* @see TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
}
public void testLectureProfils() throws Exception {
Database db = null;
URL baseConfig = null;
ArrayList liste = null;
log.info("\n\nlectureProfils()");
db = jdo.getDatabase();
db.setAutoStore(false);
db.begin();
Profil profil = null;
ArrayList lesProfils = new ArrayList();
OQLQuery oql = null;
QueryResults results = null;
int nbElts = 0;
String paramOrganisme = "National";
String paramProfil = "Technicien";
oql = db.getOQLQuery(OQL_LES_PROFILS);
oql.bind(paramOrganisme);
oql.bind(paramProfil);
// Ex�cuter la requ�te
results = oql.execute();
// balayer les objets de la collection
while (results.hasMore()) {
nbElts++;
profil = (Profil) results.next();
assertNotNull (profil);
assertEquals ("Technicien", profil.getMnemonique());
lesProfils.add(profil);
log.info(profil.getIdProfil() + " - " +
profil.getMnemonique()+ " - " + profil.getOrganisme()+ " - " +
profil.getNumVersion());
for (Iterator iter =
profil.getListeHabilitation().iterator(); iter.hasNext();) {
Habilitation element = (Habilitation)
iter.next();
log.info(" --> " +
element.getIdHabilitation()+ " - " + element.getAction()+ " - " +
element.getDroitAssocie());
}
}
db.commit();
db.close();
}
}
___________________
CREDI RA
Sylvie Palluel
[EMAIL PROTECTED]
___________________
-----Message d'origine-----
De : Ralf Joachim [mailto:[EMAIL PROTECTED]
Envoy� : lundi 6 juin 2005 14:18
� : [email protected]
Objet : Re: [castor-user] RE : [castor-user] How to optimize collection
queries ?
Hi Silvie,
I have some ideas how to work around your performance problems but
before explaining them I'd like to know a little more about how your
application. Also I want you to do some small tests.
1. Does the load behavier change if you use 'vector' or 'arraylist' as
collection types for Profile.listHabilitation instead of 'collection'?
2. Does the load behavier change if you remove the depends at
Habilitation.profile?
3. Which get/set/add methods for listHabilitation have you defined at
Profile and how do they look like? If you have set and add methods
defined, which one is used by castor?
4. When you are loading the Profile with its Habilitations do you need
write access or would readonly access be enough? Maybe you can also post
a short snap of that code if that's not to complicated.
5. Is castor the only application that access this tables of your
database or are there other systems with concurrent access to this data?
6. You have no <cache-type> definition in your mapping. ATM I don't know
which setting is used by castor whenh this is absend. May you are
someone else educate me about that? Is this my intension?
Regards
Ralf
SYLVIE PALLUEL schrieb:
Werner,
I'm using Castor 0.9.6.
And I had traces in mysql logs :
1 SQL query to get Profil, and all idHabilitation (left outer join),
and 500 SQL queries (The criteria is on idHabilitation ) to get the 500
habilitations :
SELECT * FROM SCA_PROF_HABILITATION WHERE
SCA_PROF_HABILITATION.idHabilitation = 1;
SELECT * FROM SCA_PROF_HABILITATION WHERE
SCA_PROF_HABILITATION.idHabilitation = 2;
...
Sylvie.
___________________
CREDI RA
Sylvie Palluel
[EMAIL PROTECTED]
___________________
-----Message d'origine-----
De : Werner Guttmann [mailto:[EMAIL PROTECTED]
Envoy� : lundi 6 juin 2005 12:18
� : [email protected]
Objet : RE: [castor-user] How to optimize collection queries ?
Sylvie,
what version of Castor are you using ? If it's 0.9.6 or above (e.g.
CVS),
we could have a look at the logs to see what SQL query is issued against
the mySQL initially.
Werner
wg> -----Original Message-----
wg> From: SYLVIE PALLUEL [mailto:[EMAIL PROTECTED]
wg> Sent: Monday, June 06, 2005 11:26 AM
wg> To: [email protected]
wg> Cc: [email protected]
wg> Subject: [castor-user] How to optimize collection queries ?
wg>
wg>
wg> Hi,
wg>
wg> I have a big problem of performance...
wg>
wg> I have two classes: the first one is Profil which has a
wg> collection of
wg> Habilitation (may be 500 elements).
wg>
wg> When I want to get , by a jdo query, a Profil and all his
wg> Habilitation(s),
wg> I've seen in MySql log that there are 1 SQL query to get
wg> Profil, and 500 SQL
wg> queries (The criteria is on idHabilitation ) to get the 500
wg> habilitations
wg> ...
wg> SELECT * FROM SCA_PROF_HABILITATION WHERE
wg> SCA_PROF_HABILITATION.idHabilitation = 1;
wg>
wg> SELECT * FROM SCA_PROF_HABILITATION WHERE
wg> SCA_PROF_HABILITATION.idHabilitation = 2;
wg>
wg> ....
wg>
wg>
wg>
wg> Is there something wrong in my classes?
wg>
wg> I thought it was due to the lazy mode, so I took it off.
wg> But the same thing seems to occur.
wg>
wg> Is there a way to get all the habilitations with only one
wg> SQL query (The
wg> criteria should be on idProfil) like this :
wg>
wg> SELECT * FROM SCA_PROF_HABILITATION WHERE
wg> SCA_PROF_HABILITATION.idProfil =
wg> SCA_PROFIL.idProfil;
wg>
wg> Here are the classes Pofil, and Habilitation.
wg>
wg> Thanks for your help.
wg>
-------------------------------------------------
If you wish to unsubscribe from this list, please
send an empty message to the following address:
[EMAIL PROTECTED]
-------------------------------------------------