I've used "select from X.class.getName()" to get all records of class X, but if there is a lot of records, it might take a long time to get the results.
I just want a count of how many records are there in the Datastore, what's the fastest query to get this number ? Is there something like "select COUNT() X.class.getName()" that can return , for example, 234000 [ the count of all records ] ?
See What's the best way to count results in GQL?
(short answer is that you should store the amount of object and update it whenver you add/remove objects from the datastore)
Related
I'm trying to build a Pagination inside my system. In DAO i'm using "setFirstResult()" and "setMaxResults()" to limit the amount of rows returned.
Look:
Query query = entityManager.createNamedQuery(namedQuery);
if (firstResult != null) {
query.setFirstResult(firstResult);
}
if (maxResult != null) {
query.setMaxResults(maxResult);
}
List returnList = query.getResultList();
But for pagination works i need to know the amount of rows without limitation (firstResult() and maxResults()).
If i have this query:
SELECT * FROM MyEntity e WHERE e.car = :carParam OFFSET 10 LIMIT 20
i would like to count like this
SELECT Count(*) FROM MyEntity e WHERE e.car = :carParam
But I want to avoid create another query manually for each Entity, how can i do a count() without force creating a new count() query ?
There is no way to calculate the total count of results without using Criteria API or (as you said) creating another query manually. Both of them will cause to a separate query against database to calculate the total counts. I had some experiences in this context. It may doubles your response time if your query is going to be run on a huge data set or if you have a large number of concurrent users.
I think the best way to prevent such an overhead on your DBMS is to display a "load more" link at the end of the search results. I highly recommend such approach if displaying total count is not part of your main business or is not forced by the client.
Take a look at this link (if you've not checked it before)
In my GAE application I have a survey. For example one question is "where do you live?".
If we are using the google guestbook example application the key would be guestbook, and in this I have created smaller keys like address, content2, content3. I have no problem posting or retrieving the individual results such as: "Fred MALE 24 Tokyo" "content1, gender, age, place". However on a separate page I want to show the total amount of people who took the survey; 10 people answered the survey - 3 Males 7 FEMALES. I also want to show results such as "10 people answered the survey in Tokyo." Can someone explain a way to count like this with the datastore? It would also help if your answer was in the context of Google`s guestbook example,or another simple example of GAE. お願いします!
There is count, see https://developers.google.com/appengine/docs/python/datastore/queryclass#Query_count
However see the notes in there. In short:
its time is proportional to the number of elements being counted
If you have many elements it will timeout because of (1) so you would need to use limit an paginate client-side.
its faster than iterating, but by a constant factor (because of #1)
For many elements your direction is to either use something like mapreduce, use cloud sql (easiest but $) or to maintain the counts yourself, usually with sharding and/or using memcached to improve performance and greatly reduce chances that simultaneous operations could lose data (because memcached supports atomic addition operations)
Do you mean a query like -
select count(*) from questionaires where sex = 'M'
I dont think you can return this from GAE datastore
The options are -
Return a list from a query and output its size
#SuppressWarnings("unchecked")
public List<Users> Users() {
PersistenceManager pm = getPersistenceManagerFactory().getPersistenceManager();
String query = "select from " + User.class.getName();
return (List<User>) pm.newQuery(query).execute();
}
Maintain a count on these fields in the datastore
I have a table with group and permission column. I want to find the max permission from a list of group. I am using java and oracle database, I thought of two ways to do this:
Way 1:
in java loop through the group list
result = select permission from table where group = currentgroup
if result > max, max = result
Way 2:
max = select max(permission) from table where group in (group list)
I thought way 2 would be faster, but then group list can be very long and I dont know if it is a good idea to have long list in a single sql query.
From the information you've given, the second approach is by far the best. Databases are optimised directly for these kinds of tasks, so within reason, its always best to narrow the data down with the database. The first approach means the database needs to return all values anyway, increasing processing time, bandwidth and using up memory within your java application.
How do I implement paging in Hibernate? The Query objects has methods called setMaxResults and setFirstResult which are certainly helpful. But where can I get the total number of results, so that I can show link to last page of results, and print things such as results 200 to 250 of xxx?
You can use Query.setMaxResults(int results) and Query.setFirstResult(int offset).
Editing too: There's no way to know how many results you'll get. So, first you must query with "select count(*)...". A little ugly, IMHO.
You must do a separate query to get the max results...and in the case where between time A of the first time the client issues a paging request to time B when another request is issued, if new records are added or some records now fit the criteria then you have to query the max again to reflect such. I usually do this in HQL like this
Integer count = (Integer) session.createQuery("select count(*) from ....").uniqueResult();
for Criteria queries I usually push my data into a DTO like this
ScrollableResults scrollable = criteria.scroll(ScrollMode.SCROLL_INSENSITIVE);
if(scrollable.last()){//returns true if there is a resultset
genericDTO.setTotalCount(scrollable.getRowNumber() + 1);
criteria.setFirstResult(command.getStart())
.setMaxResults(command.getLimit());
genericDTO.setLineItems(Collections.unmodifiableList(criteria.list()));
}
scrollable.close();
return genericDTO;
you could perform two queries - a count(*) type query, which should be cheap if you are not joining too many tables together, and a second query that has the limits set. Then you know how many items exists but only grab the ones being viewed.
You can do one thing. just prepare Criteria query as per your busness requirement with all Predicates , sorting , searching etc.
and then do as below :-
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Feedback> criteriaQuery = criteriaBuilder.createQuery(Feedback.class);
//Just Prepare your all Predicates as per your business need.
//eg :-
yourPredicateAsPerYourBusnessNeed = criteriaBuilder.equal(Root.get("applicationName"), applicationName);
criteriaQuery.where(yourPredicateAsPerYourBusnessNeed).distinct(true);
TypedQuery<Feedback> criteriaQueryWithPredicate = em.createQuery(criteriaQuery);
//Getting total Count Here
Long totalCount = criteriaQueryWithPredicate.getResultStream().distinct().count();
Now we have our actual data with us as above with total count , right.
So now we can apply pagination on the data we have in our hand above , as below :-
List<Feedback> feedbackList = criteriaQueryWithPredicate.setFirstResult(offset).setMaxResults(pageSize).getResultList();
Now You can prepare a wrapper with your List return by DB along with the totalCount , startingPageNo that is offset here in this case, page Size etc and can return to your service / controller class.
I am 101 % sure , this will solve your problem, Because I was facing same problem and sorted it out same way.
Thanks- Sunil Kumar Mali
You can just setMaxResults to the maximum number of rows you want returned. There is no harm in setting this value greater than the number of actual rows available. The problem the other solutions is they assume the ordering of records remains the same each repeat of the query, and there are no changes going on between commands.
To avoid that if you really want to scroll through results, it is best to use the ScrollableResults. Don't throw this object away between paging, but use it to keep the records in the same order. To find out the number of records from the ScrollableResults, you can simply move to the last() position, and then get the row number. Remember to add 1 to this value, since row numbers start counting at 0.
I personally think you should handle the paging in the front-end. I know this isn't that efficiënt but at least it would be less error prone.
If you would use the count(*) thing what would happen if records get deleted from the table in between requests for a certain page? Lots of things could go wrong this way.
I have basically the same problem outlined in this question, however I am using Microsoft Access as a database instead of MySQL. The result of which is that SQL_CALC_FOUND_ROWS doesn't seem to be available to me. Believe me, I want to switch, but for the moment it is out of the question.
I have a query that aggregates a number of rows, essentially looking for repeat rows based on certain keys, using a group by. It looks something like this:
Select key1, key2, key3, Count(id)
from table
group by key1, key2, key3
having Count(id) > 1
I need to determine the number of rows (or groupings) that query will return.
The database is being accessed through Java, so in theory I could simply run the query, and cycle through it twice, but I was hoping for something faster and preferably SQL based. Any ideas?
MS Access's record count should give you what you need, or am I missing something?
If you need distinct values from keys, try this
SELECT COUNT(*) AS Expr2
FROM (
SELECT DISTINCT [key1] & "-" & [key2] & "-" & [key3] AS Expr1
FROM Table1
) AS SUB;
When you create the Statement object, you can declare it to be scrollable. Then the first thing you do is scroll to the end and get the record number. As you're looking at the last record, this will be the number of records in the result set. Then scroll back to the beginning and process normally. Something like:
Statement st=connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs=st.executeQuery(myQueryString);
boolean any=rs.last();
int count = any ? count=getRow() : 0;
... do whatever with the record count ...
rs.first();
while (rs.next())
{
... whatever processing you want to do ...
}
rs.close();
... etc ...
I have no idea what the performance implications of doing this with MS Access will be, whether it can jump directly to the end of the result set or if it will have to sequentially read all the records. Still, it should be faster than executing the query twice.