Is it possible to execute query independently on each partition using colocated computing in IgniteCallable without explicitly joining on keys? - ignite

I have one client code which does get all the keys and then call the affinityCall which execute on server-node
Code on client side for computing on each partition
Map<Integer, List<Integer>> partitionMap = new HashMap<>();
for(Integer affKey : affKeys) {
Integer partitionId = affinityFunction.partition(affKey);
partitionMap.computeIfAbsent(partitionId, k -> new ArrayList<>()).add(affKey);
}
Collection<IgniteFuture<Map<Integer, Double>>> futures = new ArrayList<>();
Collection<String> cacheList = new ArrayList<>();
cacheList.add(CACHE_NAME);
for (int partitionId : partitionMap.keySet()) {
IgniteFuture<Map<Integer, Double>> future = compute.affinityCallAsync(cacheList, partitionId,
new Worker(CACHE_NAME, partitionMap.get(partitionId)));
futures.add(future);
}
Code for the worker is
public class Worker implements IgniteCallable<Map<Integer, Double>> {
#IgniteInstanceResource
private Ignite ignite;
private String cacheName;
private List<Integer> keys;
public Worker(String cacheName, List<Integer> keys){
this.cacheName = cacheName;
this.keys = keys;
}
#Override
public Map<Integer, Double> call() throws Exception {
IgniteCache<Object, Object> cache = ignite.cache(cacheName);
SqlFieldsQuery query =
new SqlFieldsQuery("select affKey, sum(count) from Summary s
join table(affKey integer = ?) a
on a.affKey = s.affKey
join table(studyId integer = ?) st
on st.studyId = s.studyId
group by affKey")
.setArgs((Object) keys.toArray());
Map<Integer, Double> result = new HashMap<>();
try (QueryCursor<List<?>> cursor = cache.query(query)) {
for (List<?> record : cursor) {
Integer affKey = (Integer) record.get(0);
Double sum = (Double) record.get(1);
result.put(affKey, sum);
}
}
return result;
}
}
In above case I'm joining on all the keys present in the partition. can anybody help how can we get rid of the extra join here.
More specifically this is query on which I'm working on.
public SqlFieldsQuery getQueryStringForGroup1() {
String queryString = "select g.geneId as geneId, sum(count) as count, " +
"sum(g.rawMean) as sumRawMean, " +
"sum(g.squareRawMean) as sumSquareRawMean, " +
"sum(g.rawSess) as rawSess, " +
"sum(g.mean) as sumMean, " +
"sum(g.squareMean) as sumSquareMean, " +
"sum(g.squareSd) as sEss, " +
"sum(g.greaterThan0) as sumGreaterThan0 " +
"from GeneSummary g " +
"join table(geneId integer = ?1) gn on g.geneId = gn.geneId " +
(filter.getStudyId().isEmpty() ? ""
: "join table(studyId integer = ?4) s on g.studyId = s.studyId ")
+
(filter.getCellType().isEmpty() ? ""
: "join table(cellType integer = ?7) ct on g.cellType = ct.cellType ")
+
(filter.getTissueType().isEmpty() ? ""
: "join table(tissueType integer = ?6) t on g.tissueType = t.tissueType ")
+
(filter.getCondition().isEmpty() ? ""
: "join table(condition integer = ?5) cd on g.condition = cd.condition ")
+
(filter.getAge().isEmpty() ? ""
: "join table(age integer = ?3) a on g.age = a.age ")
+
(filter.getGender().isEmpty() ? ""
: "join table(gender integer = ?2) gd on g.gender = gd.gender ")
+
"group by g.geneId";
SqlFieldsQuery query = new SqlFieldsQuery(queryString).setArgs(
(Object) geneMap.keySet().toArray(),
(Object) filter.getGender().toArray(),
(Object) filter.getAge().toArray(),
(Object) filter.getStudyId().toArray(),
(Object) filter.getCondition().toArray(),
(Object) filter.getTissueType().toArray(),
(Object) filter.getCellType().toArray());
//.setPartitions(this.partitionId);
// query.setPartitions(this.partitionId);
return query;
}
As you mentioned in the comment I modified argument to set for the query.
Modified query looks like this.
public SqlFieldsQuery getQueryStringForGroup1() {
String queryString = "select g.geneId as geneId, sum(count) as count, " +
"sum(g.rawMean) as sumRawMean, " +
"sum(g.squareRawMean) as sumSquareRawMean, " +
"sum(g.rawSess) as rawSess, " +
"sum(g.mean) as sumMean, " +
"sum(g.squareMean) as sumSquareMean, " +
"sum(g.squareSd) as sEss, " +
"sum(g.greaterThan0) as sumGreaterThan0 " +
"from GeneSummary g " +
// "join \"GeneName\".\"GENENAME\" gn on g.geneId = gn.geneId and gn.partitionId
// = ?1 " +
// "join table(geneId integer = ?1) gn on g.geneId = gn.geneId " +
(filter.getStudyId().isEmpty() ? ""
: "join table(studyId integer = ?4) s on g.studyId = s.studyId ")
+
(filter.getCellType().isEmpty() ? ""
: "join table(cellType integer = ?7) ct on g.cellType = ct.cellType ")
+
(filter.getTissueType().isEmpty() ? ""
: "join table(tissueType integer = ?6) t on g.tissueType = t.tissueType ")
+
(filter.getCondition().isEmpty() ? ""
: "join table(condition integer = ?5) cd on g.condition = cd.condition ")
+
(filter.getAge().isEmpty() ? ""
: "join table(age integer = ?3) a on g.age = a.age ")
+
(filter.getGender().isEmpty() ? ""
: "join table(gender integer = ?2) gd on g.gender = gd.gender ")
+
"group by g.geneId";
SqlFieldsQuery query = new SqlFieldsQuery(queryString);
if (!filter.getCellType().isEmpty())
query.setArgs(
(Object) geneMap.keySet().toArray(),
(Object) filter.getGender().toArray(),
(Object) filter.getAge().toArray(),
(Object) filter.getStudyId().toArray(),
(Object) filter.getCondition().toArray(),
(Object) filter.getTissueType().toArray(),
(Object) filter.getCellType().toArray());
if (!filter.getTissueType().isEmpty())
query.setArgs(
(Object) geneMap.keySet().toArray(),
(Object) filter.getGender().toArray(),
(Object) filter.getAge().toArray(),
(Object) filter.getStudyId().toArray(),
(Object) filter.getCondition().toArray(),
(Object) filter.getTissueType().toArray());
if (!filter.getCondition().isEmpty())
query.setArgs(
(Object) geneMap.keySet().toArray(),
(Object) filter.getGender().toArray(),
(Object) filter.getAge().toArray(),
(Object) filter.getStudyId().toArray(),
(Object) filter.getCondition().toArray());
if (!filter.getStudyId().isEmpty())
query.setArgs(
(Object) geneMap.keySet().toArray(),
(Object) filter.getGender().toArray(),
(Object) filter.getAge().toArray(),
(Object) filter.getStudyId().toArray());
if (!filter.getAge().isEmpty())
query.setArgs(
(Object) geneMap.keySet().toArray(),
(Object) filter.getGender().toArray(),
(Object) filter.getAge().toArray());
if (!filter.getGender().isEmpty())
query.setArgs(
(Object) geneMap.keySet().toArray(),
(Object) filter.getGender().toArray());
query.setPartitions(this.partitionId);
return query;
}
Workaround to it was set atleast last argument in the query.
Now my question here is, which approach is better here ?
With join on affinity key or querying on each partition.

With the caveat that I've not studied your query, you can limit a query to a specific partition like this:
var q = new SqlFieldsQuery("select * from table")
.setPartitions(1, 2, 3);

Related

Prepare Statement very slow compare with direct query | Oracle DB

I have a prepared statement in my application and it takes 3 minutes to give an results. However, same query i have executed in sql developer and it only takes less than 0.1 seconds to give the results. I have done research on this throughout last week and I couldn't find a proper solution. Here is my code.
public List<ResponseDto> loadData(RequestDto request) throws SQLException {
List<ResponseDto> responseDto = new ArrayList<>();
int sortBy = request.getSortBy();
String sql = "SELECT *" +
"FROM (SELECT r.*, ROWNUM RNUM, COUNT(*) OVER () RESULT_COUNT " +
" FROM (SELECT *" +
"FROM" +
" (SELECT r.VALUE_4," +
" r.DATE," +
" r.ID," +
" r.AMOUNT," +
" r.TO_AGENT_ID," +
" r.FROM_AGENT_ID," +
" a.NAME," +
" r.VALUE_2," +
" r.VALUE_1," +
" r.STATUS," +
" r.VALUE_3," +
" r.TEXT" +
" FROM MY_TABLE r" +
" INNER JOIN AGENT a " +
" ON a.AGENT_ID=r.TO_AGENT_ID" +
" WHERE r.STATUS = 1 " +
" AND r.ID IN" +
" (SELECT T.ID FROM TEST_TABLE T" +
" INNER JOIN AGENT af" +
" ON af.AGENT_ID = T.FROM_AGENT_ID " +
" INNER JOIN AGENT at" +
" ON at.AGENT_ID=T.TO_AGENT_ID" +
" WHERE T.FROM_AGENT_ID=?";
StringBuilder sbQuery = new StringBuilder(sql);
if (request.getToAgentId() != 0) {
sbQuery.append(" AND T.TO_AGENT_ID = ? ");
} else if (request.getQueryParam() != null && !request.getQueryParam().equalsIgnoreCase("")) {
sbQuery.append(" AND UPPER(at.NAME) like UPPER( ? ) ");
}
String secondPart =
" AND T.STATUS = 1" +
" AND TO_DATE(T.DATE) BETWEEN TO_DATE(?, 'yyyy-MM-dd') AND TO_DATE(?, 'yyyy-MM-dd')" +
" ) " +
" or r.VALUE_3=?";
sbQuery.append(secondPArt);
if (sortBy == 1) {
sbQuery.append(" ORDER BY a.NAME ");
} else if (sortBy == 2) {
sbQuery.append(" ORDER BY r.AMOUNT ");
} else if (sortBy == 3) {
sbQuery.append(" ORDER BY r.VALUE_4 ");
}
if (request.getSortingOrder() == 1) {
sbQuery.append("DESC ");
} else if (request.getSortingOrder() == 2) {
sbQuery.append("ASC ");
}
sbQuery.append(" )) R)" +
"WHERE RNUM between ? and ?");
String sqlq = sbQuery.toString();
log.info(sqlq);
try(Connection con = dataSource.getConnection(); PreparedStatement pstmt = con.prepareStatement(sbQuery.toString()) ) {
con.setAutoCommit(false);
String nameParam = "%" + request.getQueryParam() + "%";
pstmt.setLong(1, request.getFromAgentId());
if (request.getToAgentId() != 0) {
pstmt.setLong(2, request.getToAgentId());
} else if(request.getQueryParam() != null && !request.getQueryParam().equalsIgnoreCase("")) {
pstmt.setString(2, request.getQueryParam());
}
pstmt.setString(3, request.getFromDate());
pstmt.setString(4, request.getToDte());
pstmt.setString(5, request.getQueryParam());
pstmt.setLong(6, request.getFromIndex());
pstmt.setLong(7, request.getToIndex());
responseDto = helperMethod(pstmt);
con.commit();
} catch (SQLException e) {
log.error(e.getMessage());
throw e;
}
return responseDto;
}
public List<MyDto> helperMethod(PreparedStatement pstmt) throws SQLException {
List<MyDto> myDtoList = new ArrayList<>();
try( ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
MyDto myDto = new MyDto();
myDto.setValue4(rs.getLong("VALUE_4"));
myDto.setDate(rs.getDate("DATE"));
myDto.setTransactionId(rs.getLong("ID"));
myDto.setAmount(rs.getLong("AMOUNT"));
myDto.setToAgentId(rs.getLong("TO_AGENT_ID"));
myDto.setFromAgentId(rs.getLong("FROM_AGENT_ID"));
myDto.setName(rs.getString("NAME"));
myDto.setValue2(rs.getLong("VALUE_2"));
myDto.setValue1(rs.getLong("VALUE_1"));
myDto.setStatus(rs.getInt("STATUS"));
myDto.setValue3(rs.getString("VALUE_3"));
myDto.setText(rs.getString("TEXT"));
myDtoList.add(myDto);
}
}catch (Exception ex){
log.error(ex.getMessage());
throw ex;
}
return myDtoList;
}
As I said, same query works with in milliseconds. I really don't know what i am doing wrong here.
Any help would be grateful !
This is not a direct answer, but may hopefully point you in the right direction. First off, depending on your conditionals, there are different variations of what SQL is executed. I would try the following:
Edit the select string and embed a unique comment in it so we can find it in the next step. Example : "select /*mytest*/ * from ..."
Execute your program. Then locate the query in the v$sqlarea such as: select sql_id from v$sqlarea where instr(sql_fulltext,'mytest') > 0;
using the sql_id value from Step #2, execute SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR('sql_id',0));
this will show you the execution plan, and hopefully you will see the difference maybe a full table scan is happening or index not getting used. etc. Do similar steps for the direct sql query that is faster and see what the differences are.

jdbcTemplate and raw JSON column

Suppose I query a table which contains raw json in a column, or create json myself with a subquery like this:
select
p.name,
(select json_build_array(json_build_object('num', a.num, 'city', a.city)) from address a where a.id = p.addr) as addr
from person p;
How can I instruct Spring's NamedParameterJdbcTemplate not to escape
the addr column but leave it alone?
So far it insists returning me something like this:
[{
name: "John",
addr: {
type: "json",
value: "{"num" : "123", "city" : "Luxembourg"}"
}
}]
This is the working solution.
Service:
#Transactional(readOnly = true)
public String getRawJson() {
String sql = "select json_agg(row_to_json(json)) from ( "
+ "select "
+ "p.id, "
+ "p.name, "
+ "(select array_to_json(array_agg(row_to_json(c))) from ( "
+ " ... some subselect ... "
+ ") c ) as subq "
+ "from person p "
+ "where type = :type "
+ ") json";
MapSqlParameterSource params = new MapSqlParameterSource("type", 1);
return jdbcTemplate.queryForObject(sql, params, String.class);
}
Controller:
#ResponseBody
#GetMapping(value = "/json", produces = MediaType.APPLICATION_JSON_VALUE)
public String getRawJson() {
return miscService.getRawJson();
}
The key is the combination of json_agg and row_to_json / array_to_json plus returning a String to avoid any type conversions.

Restar Loader can't update gridview

I've got two SQL tables inner join with content provider query builder. My loader shows the first in a gridview like a charm. The second table has been created to show a favorite list and so it has primary key, foreign key and another column. By the way when I try to retrieve value from this one I get null. Some suggestions, please!
I have this in content provider:
static {
sMovieByFavoriteQueryBuilder = new SQLiteQueryBuilder();
sMovieByFavoriteQueryBuilder.setTables(
MoviesContract.FavoriteEntry.TABLE_NAME + " INNER JOIN " +
MoviesContract.MovieEntry.TABLE_NAME +
" ON " + MoviesContract.FavoriteEntry.TABLE_NAME +
"." + MoviesContract.FavoriteEntry.COLUMN_FAVORITE_KEY +
" = " + MoviesContract.MovieEntry.TABLE_NAME +
"." + MoviesContract.MovieEntry._ID);
}
private static final String sFavoriteSelection =
MoviesContract.FavoriteEntry.TABLE_NAME +
"." + MoviesContract.FavoriteEntry.COLUMN_MOVIE_ID + " = ? AND " +
MoviesContract.FavoriteEntry.COLUMN_MOVIE_POSTER + " = ? AND " +
MoviesContract.MovieEntry.COLUMN_RELEASE_DATE + " = ? AND " +
MoviesContract.MovieEntry.COLUMN_MOVIE_POSTER + " = ? AND " +
MoviesContract.MovieEntry.COLUMN_ORIGINAL_TITLE + " = ? AND " +
MoviesContract.MovieEntry.COLUMN_SYNOSIS + " = ? AND " +
MoviesContract.MovieEntry.COLUMN_USER_RATING + " = ? ";
I call this method by uri from fragment:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
getLoaderManager().initLoader(MOVIES_LOADER, null, this);
getLoaderManager().initLoader(FAVORITE_LOADER, null, this);
super.onActivityCreated(savedInstanceState);
}
void onSortChanged() {
System.out.println("onSortChanged: true");
updateMovies();
getLoaderManager().restartLoader(MOVIES_LOADER, null, this);
System.out.println("LoaderManager: " + getLoaderManager().restartLoader(MOVIES_LOADER, null, this));
}
void onFavorite() {
getLoaderManager().restartLoader(FAVORITE_LOADER, null, this);
mMoviesAdapter.setSelectedIndex(mPosition);
mMoviesAdapter.notifyDataSetChanged();
}
private void updateMovies() {
PopularMoviesSyncAdapter.syncImmediately(getActivity());
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
if (MainActivity.mFavorite == true) {
String sortOrder = MoviesContract.FavoriteEntry.COLUMN_FAVORITE_KEY;
String sortSetting = Utility.getPreferredSort(getActivity());
Uri movieFavoriteUri = MoviesContract.MovieEntry.buildMovieWithSortDate(sortSetting, System.currentTimeMillis());
System.out.println("movieFavoriteUri: " + movieFavoriteUri);
cursorFav = new CursorLoader(getActivity(),
movieFavoriteUri,
FAVORITE_COLUMNS,
null,
null,
sortOrder);
return cursorFav;
} else {
String sortOrder = MoviesContract.MovieEntry.COLUMN_DATE;
String sortSetting = Utility.getPreferredSort(getActivity());
System.out.println("sortSetting: " + sortSetting);
Uri movieForSortUri = MoviesContract.MovieEntry.buildMovieSort(sortSetting);
System.out.println("movieForSortUri: " + movieForSortUri);
cursorMov = new CursorLoader(getActivity(),
movieForSortUri,
MOVIES_COLUMNS,
null,
null,
sortOrder);
return cursorMov;
}
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mMoviesAdapter.swapCursor(data);
if (mPosition != GridView.INVALID_POSITION) {
// If we don't need to restart the loader, and there's a desired position to restore
// to, do so now.
mGridView.smoothScrollToPosition(mPosition);
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mMoviesAdapter.swapCursor(null);
}
Instead of:
sMovieByFavoriteQueryBuilder.setTables(
MoviesContract.FavoriteEntry.TABLE_NAME + " INNER JOIN " +
MoviesContract.MovieEntry.TABLE_NAME +
" ON " + MoviesContract.FavoriteEntry.TABLE_NAME +
"." + MoviesContract.FavoriteEntry.COLUMN_FAVORITE_KEY +
" = " + MoviesContract.MovieEntry.TABLE_NAME +
"." + MoviesContract.MovieEntry._ID);
Create a string so you can debug it easy.
strTables = MoviesContract.FavoriteEntry.TABLE_NAME + " INNER JOIN " +
MoviesContract.MovieEntry.TABLE_NAME +
" ON " + MoviesContract.FavoriteEntry.TABLE_NAME +
"." + MoviesContract.FavoriteEntry.COLUMN_FAVORITE_KEY +
" = " + MoviesContract.MovieEntry.TABLE_NAME +
"." + MoviesContract.MovieEntry._ID);
sMovieByFavoriteQueryBuilder.setTables(strTables);
Then try to run that join direct on db. My guess is the query have some issues.
I checked and the query works good. But my method can't return anything
private Cursor getMovieByFavorite(Uri uri, String[] projection, String movieId) {
String sortSetting = MoviesContract.MovieEntry.getFavoriteFromUri(uri);
long date = MoviesContract.MovieEntry.getDateFromUri(uri);
String[] selectionArgs;
String selection;
selection = sFavoriteSelection;
selectionArgs = new String[]{sortSetting};
return sMovieByFavoriteQueryBuilder.query(mOpenHelper.getReadableDatabase(),
projection,
selection,
null,
null,
null,
movieId
);
}

oracle pass list of string as parameter

I want to pass list of string as parameter
when my query is generated from my application I have this sql code :
SELECT * FROM Transfers TRANSFERS
LEFT OUTER JOIN correspondence_copy CORRESPCPY on CORRESPCPY.ID_COPY = TRANSFERS.ID_COPY
WHERE TRANSFERS.ORDERNBR in ('[236359981, 236359982, 236359983]')
this is the source code in jave where I used List
public List<SupEntity> sendSup(List<String> listOrderNumber)
throws Exception {
String query_tr = " SELECT * ";
query_tr += " FROM Transfers TRANSFERS ";
query_tr +=" LEFT OUTER JOIN correspondence_copy CORRESPCPY on CORRESPCPY.ID_COPY = TRANSFERS.ID_COPY " ;
query_tr +=" WHERE TRANSFERS.ORDERNBR in ('" +listOrderNumber + "')";
SQLQuery sqlQuery = this.getSession().createSQLQuery(query_tr);
sqlQuery.setResultTransformer(Transformers.aliasToBean(
SupEntity.class));
List list = sqlQuery.list();
return list;
}
I call this methode from this code :
public SupListEntity getsupList(
HttpServletRequest request,
SupListEntity supListEntity)
throws Exception {
List<String> list = new ArrayList<String>();
List<CorrespondenceEntity> sendsupList =new ArrayList<SupEntity>();
String [] tabOrder=null;
if(supListEntity.getId()!=null)
{
tabOrder=supListEntity.getId().split(",");
if(tabOrder!=null && tabOrder.length>0)
{
for(int i=0;i<tabOrder.length;i++)
{
list.add(tabOrder[i]);
}
sendsupList = supDAO.sendSup(list);
supListEntity.setCorrespondenceList(sendsupList);
}
}
return supListEntity;
}
so the problem that my query which is generaed has this kind of code :
in ('[236359981, 236359982, 236359983]') which is false
it should be like this
in ('236359981', '236359982', '236359983')
You may try this:
String query_tr = " SELECT * ";
query_tr += " FROM Transfers TRANSFERS ";
query_tr +=" LEFT OUTER JOIN correspondence_copy CORRESPCPY on CORRESPCPY.ID_COPY = TRANSFERS.ID_COPY " ;
query_tr +=" WHERE TRANSFERS.ORDERNBR in (:list)";
SQLQuery sqlQuery = this.getSession().createSQLQuery(query_tr);
sqlQuery.setParameterList("list", listOrderNumber)

Sparql substract instance

I have an anthology, I created an interface for evaluation or there is a submit button. This button allows you to calculate the difference between the old value and the value 20. I try to select an instance with sparql and I would evaluate an instance subtracts the old value with the value 20.
valider.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Model m=ModelFactory.createMemModelMaker().createModel(null);
FileManager.get().readModel( m, owlFile );
String myOntologyName = "ProjetHela";
String uri="file:///C:/Project/Krs1.owl";
// DĂ©finition de prefixe pour simplifier l'utilisation de SPARQL
String reuses = "maj: <"+RDF.getURI()+">" ;
// String myOntologyPrefix = "PREFIX "+myOntologyName+": <"+myOntologyNS+">" ;
String myOntologyPrefix = "PREFIX "+myOntologyName+": <"+uri+">" ;
// if (liste.getSelectedItem().toString().equals("GMP: Puissance=60352 Watt,limite supérieure= 73500 Watt")) {
String queryString=
"PREFIX maj: <http://www.owl-ontologies.com/reuses.owl#>"
+ "SELECT ?hasnameevaluated"
+ " WHERE "
+ "{"
+ "?Besoin maj:hasnameevaluated ?hasnameevaluated "
+"FILTER (?hasnameevaluated - 20) "
+ " } ";
Query query = QueryFactory.create(queryString) ;
QueryExecution qexec = QueryExecutionFactory.create(query, m) ;
try {
ResultSet rs = qexec.execSelect() ;
// Affichage des resultats
for ( ; rs.hasNext() ; ){
//System.out.print("");
QuerySolution rb = rs.nextSolution() ;
String y = rb.getLiteral("hasnameevaluated").getString();
System.out.println( " " + y);
}} finally {
qexec.close() ;
}
}
}
);
but it doesn't work
please help me
FILTER (?hasnameevaluated - 20)
is a test , not an assignment of a value.
Did you mean to use:
BIND (?hasnameevaluated - 20 AS ?newvalue)
or
SELECT ?hasnameevaluated (?hasnameevaluated - 20 AS ?newvalue) WHERE