we created a custom screen which displays list of sales data based on filter conditions like (today, yesterday, this week, this month, this quarter, this year), we created a SQL view for this and then from VIEW we created and DAC and using it in custom screen. We also have filters in our screen. for filter conditions we are using view delegate and returning the data. the question is why the screen takes too long around 70 seconds to load 2K records. Is using view delegate decrease the speed of loading data. We can go with GI but we need to display images in the GRID so we opted for custom screen and also we have some report button in header which prints report. as we can't show images in GI we chose this.
The slowness you see is most likely caused by combination of two reasons.
When you use BQL view, it in fact requests only the number of records you see on the screen. For instance if you have grid with paging and only 20 records are visible on the page, the SQL select will have TOP 20 limitation. However, once you have select delegate, that optimization stops working since the framework does not know what you'd like to do with the data you select. The solution here would be to use SelectWithViewContext with DelegateResult return object instead of regular select. In that case user filtering, pagination and ordering is preserved in the select. (Use this method only if resulting records on the screen relate as 1 to 1 to the records you select. If you use any kind of aggregation or inserting records from 2 different select, that approach does not work)
Example:
protected virtual IEnumerable ardocumentlist()
{
PXSelectBase<BalancedARDocument> cmd =
new PXSelectJoinGroupBy<BalancedARDocument,
...
OrderBy<Asc<BalancedARDocument.docType, //Set necessary sorting fields: use the key fields
Asc<BalancedARDocument.refNbr>>>> //Set necessary sorting fields: use the key fields
(this);
PXDelegateResult delegResult = new PXDelegateResult
{
IsResultFiltered = true, //set these fields to indicate that the result does not need re-filtering, resorting and re-paging
IsResultTruncated = true,
IsResultSorted = true
}
foreach (PXResult<BalancedARDocument> res_record in cmd.SelectWithViewContext())
{
// add the code to process res_record
delegResult.Add(res_record);
}
return delegResult;
}
Probably you don't have proper indexes on your table since even if you select all 2k records at once it should not result in 70 seconds load time. Recommendation here would be to use the request profiler to catch the exact SQL generated (https://help-2020r2.acumatica.com/Help?ScreenId=ShowWiki&pageid=e4c450bb-86bc-4fb2-b7e6-1f715abe3c8b) and execute the SQL in MS SQL Management studio with option 'Include Actual Execution Plan' (https://learn.microsoft.com/en-us/sql/relational-databases/performance/display-an-actual-execution-plan?view=sql-server-ver15) . Usually in this mode the MS SQL server suggests the indexes needed to speed up the query execution.
Related
I need a table that shows about 2.5 million rows from an array that is already created in memory. When I create the table and add the array to the 'data' property, the browser engine runs out of memory after some (significant) time. I assume that tabulator not only creates objects for the current virtual DOM part, but for each entry in the array in advance.
So my question: is it possible to not provide the entire array, but only the the count of rows, and let tabulator ask for the content of each row via a callback only when needed for rendering. Of course it only makes sense if tabulator does not keep any data of rows that are gone out of view.
I know that this might be in conflict with some column calculation features or others, but this would be fine for my use case.
The same use case is working with canvas-datagrid, which I have tried before.
If you can use Ajax to get the data there is the Progressive Ajax Loading that will help you to load data using the pagination module to make a series of requests for part of the data set, one at a time, appending it to the table as the data arrives.
Doc is here: http://tabulator.info/docs/4.3/data#ajax-alter
Progressive loading is an option, but you still are going to run into the issue that you will have two copies of the data in memory. It will either happen automatically if in 'load' mode or manually in 'scroll' mode as you scroll through the table. The best option would seem to be to have code via say a button that loads the data using either setData() or replaceData(). Then the user could fetch either the next or previous set of data in batches.
On the Activities tab of the Contacts screen, I am pulling activity data from an outside source and creating corresponding Acumatica activities. This activity creation is a periodically schedule process, so the activities are not created real-time. Therefore the CreatedDateTime field for the external activities does not reflect the actual time that the activities happened.
However, I need these external activities to be sorted according to when they actually occurred (not according to when they were created in Acuamtica) and to be displayed in proper sequence relative to existing Acuamtica activities. But the Activities view for the Contacts graph is sorted by CreatedDateTime, so these activities are being displayed according to Acuamtica creation time not their actual time.
I can think of two possible solutions, but I cannot see a way to accomplish either one.
1. Set the CRActivity.CreatedDateTime field to be the actual activity time.
If we could set the Created Date Time to be the actual time of the activity, the default sort order for the Activities tab would correctly display the external activities in sequence of when they actually occurred. However, this field is a default system field, and I do not see a good way to force it to be anything other than the time the Acumatica object is persisted. Is there any way to specify a value for the CreatedDateTime field?
2. Modify the default sort order of the Activities tab.
We can set the StartDate of the new activities to be the actual time that they occurred. So if we could order the Activities grid by Start Date rather than by Created Date Time, that would also achieve the desired affect. If the Activities view were a straightforward PXSelect, we could simply create a new PXSelect statement with the order by we want in our graph extension and use that as the data member for the grid. However, the Activities view is not simple and the OrderBy is buried inside the GenerateOriginalCommand method of the CRActivityListBase class. Is there anyway to override this OrderBy in way that takes advantage of all the functionality of CRActivityListBase?
Is there an acceptable way to use either of these approaches, or is there an alternative approach that would display the activities sorted by actual time?
You can replace Sorting utilizing OrderByNew as below.
public class ContactMaintPXExt : PXGraphExtension<ContactMaint>
{
public override void Initialize()
{
Base.Activities.OrderByNew<OrderBy<Desc<CRActivity.startDate>>>();
}
}
I'm working through some poor performance when exporting data (StockItems) from Acumatica using a generic inquiry. The issue I'm having is that Acumatica is going after every item in the result set and then getting the notes for each item.
Is there a way to disable this for generic inquiry screens? I don't need notes, I just want the data. My main query finishes in .02 seconds but then there is another 2-3 seconds of SQL time while it gets the notes.
If you use DACs made from SQL Views the results grid doesn't add the notes. But once you join a DAC that is note enabled they start to populate in the results grid.
I have a form with 4 datasources. It is in listpage style and have Datasource1 (big table with lots of relations, columns, and indexes) shown in grid. When I open this form it takes like 200ms to open it but when I refresh it it takes 13s to refresh.
I used the Code profiler tool and I find out that the time is consumed in Datasource1 in executeQuery() method by command super();
When the executeQuery() is called from form by
Datasource1_ds.executeQuery();
it takes 200ms to call it.
There is like 15 columns in grid on form and sorting by one takes a little less than 1s.
So my question is. What is called in super(); when the form is refreshed by task F5 and not called by openning form and calling Datasource1_ds.executeQuery();?
I try to use Code profiler with different setings and actions, debug the code in various action done, use Visual Studio Profiler, use Activity Monitor in Microsoft SQL server on Microsoft Dynamics AX database, changes the Datasource1 table, with no luck.
Everytime I end up on the super(); Only time when the refresh is fast is when I have filters on the grid and it shows less rows. (I try to use VisibleRows property on grid but it does not help.)
I am using Microsoft Dynamics AX 2012 R2
I would suggest to capture with SQL Server Profiler queries that are executed (1) on initial executeQuery() when ListPage form is opened, then (2) on invocation of executeQuery() on form refresh.
Comparison of execution plans of these two queries must show the bottleneck. You may capture Showplan XML event.
If you add grouping to a list view does it inheretly improve performance when you navigate to the view in the sharepoint page? i.e. if you use grouping, does sharepoint retrieve data when you click the [+] icon (using an Ajax call)? or is the data already retrieved beforehand?
Many thanks.
when u use grouping by default all your group document are not loaded first time. when u expand group it load all document.
After that using JavaScript it change the property from display none to display block and display block to display none and so on.
so according to performance it load all document first time but it's quick.
This is same for list also
My experience is that using groupings loads all data at once. So if you have a list with 1000 items and you display a grouped view, you may experience very slow loading.