I currently have a sharepoint2010 list that contains roughly 200,000 records.
I want to get each record, tweak it, massage it, and store it in a SQL table.
As of now, I am using the sharepoint 2010 web service method GetListItems like so...
System.Xml.XmlNode nodeListItems = client.GetListItems("guid", "", query, viewFields, RowNumber, queryOptions, null);
querying 200000 records is too much to query at once. How can I get around this? The GetListItems method takes CAML query parameters.
Is there a way to do this in increments, like say 5000 records at a time? How would one structure the CAML query to do that?
Unless someone has a better way of accomplishing this altogether?
Yes, there is, you can paginate the results. The fifth parameter is the page size, you have it set via RowNumber. Set it to 5000 if you want pages of size 5000.
Details on accessing subsequent pages can be seen from the documentation for the GetListItems method
The GetListItems method supports server-side paging. The XML data
returned by this method includes a ListItemCollectionPositionNext
attribute inside the rs:Data element that contains the information to
support paging. This string contains data for the fields in the sort
and for other items needed for paging. You should consider this string
internal and not to be modified; modifying it can produce unexpected
results. The following example shows the form of this return value
when paging is supported.
<rs:Data ListItemCollectionPositionNext="
Paged=TRUE&p_ID=100&View=
%7bC68F4A6A%2d9AFD%2d406C%2dB624%2d2CF8D729901E%7d&PageFirstRow=
101" Count=1000 >
<z:row ows_FirstName="Nancy" ows_LastName="Name" ….. />
...
</rs:Data>
To get the next page of data, the queryOption parameter is used, as
shown in the following example.
<QueryOptions>
<Paging ListItemCollectionPositionNext="
Paged=TRUE&p_ID=100&View=
%7bC68F4A6A%2d9AFD%2d406C%2dB624%2d2CF8D729901E%7d&PageFirstRow=
101" />
</QueryOptions>
So all you need to do is grab the data in that attribute from each page's result set and add it to the query to get the next page.
Related
I have a question about Pageable< T > in C#. I have table storage in Azure named- Domains. I am using Azure.Data.Tables nuget package, and to Query all the domains i am using this :
var domains = _localDomainTableClient
.Query<Domain>()
.AsPages()
.SelectMany(d => d.Values);
But i dont understant something. What if i use Query< T > without AsPages method ?
IEnumerable<Domain> domainsPAges = tableClient.Query<Domain>();
I know that AsPages() returns a collection of pages. For example if I have 10000 items in the table, Query<Domain>().AsPages() should make 10 requests to the table and return me 10 pages with 1000 items in each page (unless I changed the default value) but I don't understand what exactly is happening if I don't use AsPages() ?
Example:
IEnumerable<Domain> domainsPAges = tableClient.Query<Domain>();
Query<Domain>() return Pageble< T > but, does it make 10 requests to the table again or does it take all the elements until the memory overflows (4 MB by default) or take all the elements at once ?
I check documentation, but I couldn't find what I needed.
A collection of values that may take multiple service requests to iterate over.
A collection of values retrieved in pages
What is it even mean ?
Thanks for help.
How many requests Query will make, if AsPages() is not used?
In C#, the Query method is part of the Azure Cosmos DB SDK.
The Query<T> method will retrieve all matching results in a single request to the database. This behaviour is known as a single-partition query.
If the query involves multiple partitions, then the Query method will make multiple requests to retrieve all matching results. The exact number of requests will depend on the number of partitions involved and the size of the result set.
If the AsPages() method is not used, then the query results will be returned as a single enumerable object. If the AsPages() method is used, the query results will be returned as a sequence of pages, each containing a subset of the query results. In this case, the number of requests made will depend on the size of each page and the total number of results matching the query criteria.
What if i use Query< T > without AsPages method
In C#, if you use Query<T> without the AsPages method, you will receive all the results of the query in a single batch.
The Query<T> method returns an IEnumerable that represents the results of the query. If you do not use AsPages, the entire result set will be loaded into memory at once. This leads to high memory usage and performance can be degraded, as it can consume a lot of memory.
AsPages method also enables you to retrieve the results in a more efficient manner. It allows you to retrieve the results in smaller batches or pages, which can help reduce the memory usage and improve performance. The AsPages method returns an IAsyncEnumerable<Page<T>>, where each Page represents a page of results.
Query() return Pageble< T > but, does it make 10 requests to the table again or does it take all the elements until the memory overflows (4 MB by default) or take all the elements at once?
The behaviour of Query() depends on the implementation of the method and the underlying database system.
when you execute a query that returns a pageable result, the database will execute the query and return only a subset of the results to the application, based on the page size and the current page number. The remaining results are retrieved on subsequent requests for the next pages.
So if you call Query<Domain>() with a specific page size, it will only retrieve the number of elements specified in that page size, and not all the elements in the table.
The number of requests made to the table will depend on the number of pages that need to be retrieved to return all the results for the query.
The memory used to store the retrieved results will depend on the size of the objects retrieved and the number of objects retrieved in each page. When using pageable results, the size of the objects returned is generally limited to reduce memory usage, so it's unlikely that the memory usage will exceed the default limit of 4 MB.
For more information refer this Query table entities and SO Thread.
We have a 4 column data grid display on a page. I would like to perform a query based on each of the values within each cell of the grid i.e. 4 queries for each row.
This is so I can populate the cell with count of records in db that matches that value.
When each row gets populated by jqgrid, it fires off an ajax call for each cell.
I think it's a very bad idea since I have already discovered the browser limits the number of ajax calls to the same server.
Are there similar limits for ado.net?
I would like to batch these queries together so I do fewer calls to the db, is this what you would do?
How would you approach this?
You could combine your AJAX calls into one, the resulting object contains an array, or multiple properties for each result set, and then you run your SQL in parallel on the server.
Check out this QA for how to use options on how to use TPL and SQL.
Parallel.Foreach SQL querying sometimes results in Connection
me would suggest you to select the associated id data in the first request and populate the values in the UI.
You could either use join or left join in your first query based on your requirement and architecture and fetch the specific column value/ count(id) ( Here you mentioned as the count of records ).
Is there any way in which I can retrieve all the results from client.Search (I think this can be done using scroll API) and create a pagination for these results when displaying them? Is there any API from ES for doing so?
Or using From() and size(), can it be done?
For eg: Lets say, I have 100,000 documents on the index and when I search for a keyword it generates some 200 results. How can I use scroll, from and size to show them?
TIA
We use from and size options to implement pagination for Elasticsearch results.
The code snippet can be something like below:
def query(page)
size = 10
page ||= 1
from = (page-1) * size
# elasticsearch query with from * size options
end
You may need to know total number of results to implement pagination without sending a additional count request. To get the total results, you can use the total field of the response.
=== Updated
If you want to get the search results of the first page, then you can use query(1). If you want to get the search results of the second page, then you can use query(2) and so on.
The purpose of the scroll is slightly different. Let's say you need to get all records of the search results and the number of results are too large (eg., millions of results). If you retrieve all the data at once, it will arise a kind of memory issue or problems because of the high load. In this case, you can use scroll to fetch results step by step.
For the pagination, you don't need to get all data of the search results. You only need to get some data of a specific page. In this case, you may need to use just query with from and size options NOT scroll.
I am using OData to get records, but due to some performance issues we are having when using the SQL it generates via LINQ, we have decided to write a stored procedure to get the data (using SQL Server as our database). I know how to call the stored procedure and map the result to an entity. The thing I am confused about is when I get an $inlinecount=allpages parameter, how do I manually set the odata.count parameter instead of having OData try to do it?
I'd like to call my stored procedure, which takes in all the filters and sorts, as well as skip and top for paging, as parameters, to get the data. The problem is, I need the total count (without applying the skip/top/sorts) for the odata.count property that should be returned in the response. To even get this count, I would have to either make a second stored procedure that only takes the filters and returns a count, or possibly modify the original one to return a count as an output parameter, along with the data. Regardless, once I get that number, what do I do with it? How do I tell OData to use that as the returned odata.count property, instead of trying to apply its own magic to do so?
If you profile the db when entity framework generates the query, it executes two queries. One for the total count and another for the data. Like you say, it is a similar query, just getting the count instead of the actual data.
As far as how to return it, I have done so in the past using a PageResult<T> - this has a structure to include the count.
You should also consider how you will handle other odata query options, like select. Or, you can disable options that you don't support.
I have the following that returns a collection from Azure table storage where Skip is not implemented. The number of rows returned is approximately 500.
ICollection<City> a = cityService.Get("0001I");
What I would like to do is to be able to depending on an argument have just the following ranges returned:
records 1-100 passing in 0 as an argument to a LINQ expression
records 101-200 passing in 100 as an argument to a LINQ expression
records 201-300 passing in 200 as an argument to a LINQ expression
records 301-400 passing in 300 as an argument to a LINQ expression
etc
Is there some way I can add to the above and use link to get these ranges
of records returned:
As you already stated in your question, the Skip method is not implemented in Windows Azure Table storage. This means you have 2 options left:
Option 1
Download all data from table storage (by using ToList, see abatishchev's answer) and execute the Skip and Take methods on this complete list. In your question you're talking about 500 records. If the number of records doesn't grow too much this solution should be OK for you, just make sure that all records have the same partition key.
If the data grows you can still use this approach, but I suggest you evaluate a caching solution to store all the records instead of loading them from table storage over and over again (this will improve the performance, but don't expect this to work with very large amounts of data). Caching is possible in Windows Azure using:
Windows Azure Caching (Preview)
Windows Azure Shared Caching
Option 2
The CloudTableQuery class allows you to query for data, but more important to receive a continuation token to build a paging implementation. This allows you to detect if you can query for more data, the pagination example on Scott's blogpost (see nemensv's comment) uses this.
For more information on continuation tokens I suggest you take a look at Jim's blogpost: Azure#home Part 7: Asynchronous Table Storage Pagination. By using continuation tokens you only download the data for the current page meaning it will also work correctly even if you have millions of records. But you have to know the downside of using continuation tokens:
This won't work with the Skip method out of the box, so it might not be a solution for you.
No page 'numbers', because you only know if there's more data (not how much)
No way to count all records
If paging is not supported by the underlying engine, the only way to implement it is to load all the data into memory and then perform paging:
var list = cityService.Get("0001I").ToList(); // meterialize
var result = list.Skip(x).Take(y);
Try something like this:
cityService.Get("0001I").ToList().Skip(n).Take(100);
This should return records 201-300:
cityService.Get("0001I").ToList().Skip(200).Take(100);
a.AsEnumerable().Skip(m).Take(n)