All I want for Christmas is a real "SELECT" statem

Nobody
Member Posts: 93
Currently when we use a FINDFIRST, FINDLAST, FINDSET, FIND(‘+’), or FIND(‘-‘) NAV does a “SELECT *” or select all from the table even though we do not need all the columns. This means even though we may have an index that satisfies the WHERE and ORDER BY clauses it still has to look at the clustered index to pull the column data because it is not on the index page. In SQL 2005 we have the option to include columns in the index that are not part of the index, but adding all the columns in the table to each index so it does not have to go back to the clustered to pull the column creates massive indexes.
Example from NAV:
Code Unit 5771 - Release(SalesHeader : Record "Sales Header")
SalesLine.SETCURRENTKEY("Document Type","Document No.","Location Code");
SalesLine.SETRANGE("Document Type","Document Type");
SalesLine.SETRANGE("Document No.","No.");
SalesLine.SETRANGE(Type,SalesLine.Type::Item);
SalesLine.SETRANGE("Drop Shipment",FALSE);
SalesLine.SETRANGE("Job No.",'');
IF SalesLine.FIND('-') THEN BEGIN
First := TRUE;
REPEAT
IF (("Document Type" = "Document Type":: Order) AND
(SalesLine.Quantity >= 0)) OR
(("Document Type" = "Document Type"::"Return Order") AND
(SalesLine.Quantity < 0))
THEN
WhseType := WhseType::Outbound
ELSE
WhseType := WhseType::Inbound;
IF First OR (SalesLine."Location Code" <> OldLocationCode) OR
(WhseType <> OldWhseType)
THEN
CreateWhseRqst(SalesHeader,WhseType);
First := FALSE;
OldLocationCode := SalesLine."Location Code";
OldWhseType := WhseType;
UNTIL SalesLine.NEXT = 0;
END;
This creates the SQL statement:
SELECT * FROM "CRONUS USA, Inc_$Sales Line" WITH (UPDLOCK) WHERE (("Document Type"=?)) AND (("Document No_"=?)) AND (("Type"=?)) AND (("Drop Shipment"=?)) AND (("Job No_"=?)) ORDER BY "Document Type","Document No_","Location Code","Line No_"
The record size for this statement is 1669 bytes
Would it be possible in the future to do something like FINDFIELDS(‘+’) (“field1”, “field2”, and so on) or FINDFIELDS(‘-‘) (“field1”, “field2”, and so on) so we could pull just the fields we need? This would make query tuning much easier and help with performance and cut down on the size of the data go back and forth from the client (or middle tier) to the server.
Code Unit 5771 - Release(SalesHeader : Record "Sales Header")
SalesLine.SETCURRENTKEY("Document Type","Document No.","Location Code");
SalesLine.SETRANGE("Document Type","Document Type");
SalesLine.SETRANGE("Document No.","No.");
SalesLine.SETRANGE(Type,SalesLine.Type::Item);
SalesLine.SETRANGE("Drop Shipment",FALSE);
SalesLine.SETRANGE("Job No.",'');
IF SalesLine.FINDFIELDS('-')(“Quantity”, “Location Code”) THEN BEGIN
First := TRUE;
REPEAT
IF (("Document Type" = "Document Type":: Order) AND
(SalesLine.Quantity >= 0)) OR
(("Document Type" = "Document Type"::"Return Order") AND
(SalesLine.Quantity < 0))
THEN
WhseType := WhseType::Outbound
ELSE
WhseType := WhseType::Inbound;
IF First OR (SalesLine."Location Code" <> OldLocationCode) OR
(WhseType <> OldWhseType)
THEN
CreateWhseRqst(SalesHeader,WhseType);
First := FALSE;
OldLocationCode := SalesLine."Location Code";
OldWhseType := WhseType;
UNTIL SalesLine.NEXT = 0;
END;
If we could do something like this it would create a much more defined SQL statement that would much smaller record sizes and much easier to tune for performance because we can create an index with the select list included. This would really benefit situations were a table has a IMAGE datatype that cannot be pulled via an index seek.
SELECT “Quantity”, “Location Code” FROM "CRONUS USA, Inc_$Sales Line" WITH (UPDLOCK) WHERE (("Document Type"=?)) AND (("Document No_"=?)) AND (("Type"=?)) AND (("Drop Shipment"=?)) AND (("Job No_"=?)) ORDER BY "Document Type","Document No_","Location Code","Line No_"
The record size for this statement is 73 bytes with a little index tuning it is 64 bytes.
Example from NAV:
Code Unit 5771 - Release(SalesHeader : Record "Sales Header")
SalesLine.SETCURRENTKEY("Document Type","Document No.","Location Code");
SalesLine.SETRANGE("Document Type","Document Type");
SalesLine.SETRANGE("Document No.","No.");
SalesLine.SETRANGE(Type,SalesLine.Type::Item);
SalesLine.SETRANGE("Drop Shipment",FALSE);
SalesLine.SETRANGE("Job No.",'');
IF SalesLine.FIND('-') THEN BEGIN
First := TRUE;
REPEAT
IF (("Document Type" = "Document Type":: Order) AND
(SalesLine.Quantity >= 0)) OR
(("Document Type" = "Document Type"::"Return Order") AND
(SalesLine.Quantity < 0))
THEN
WhseType := WhseType::Outbound
ELSE
WhseType := WhseType::Inbound;
IF First OR (SalesLine."Location Code" <> OldLocationCode) OR
(WhseType <> OldWhseType)
THEN
CreateWhseRqst(SalesHeader,WhseType);
First := FALSE;
OldLocationCode := SalesLine."Location Code";
OldWhseType := WhseType;
UNTIL SalesLine.NEXT = 0;
END;
This creates the SQL statement:
SELECT * FROM "CRONUS USA, Inc_$Sales Line" WITH (UPDLOCK) WHERE (("Document Type"=?)) AND (("Document No_"=?)) AND (("Type"=?)) AND (("Drop Shipment"=?)) AND (("Job No_"=?)) ORDER BY "Document Type","Document No_","Location Code","Line No_"
The record size for this statement is 1669 bytes
Would it be possible in the future to do something like FINDFIELDS(‘+’) (“field1”, “field2”, and so on) or FINDFIELDS(‘-‘) (“field1”, “field2”, and so on) so we could pull just the fields we need? This would make query tuning much easier and help with performance and cut down on the size of the data go back and forth from the client (or middle tier) to the server.
Code Unit 5771 - Release(SalesHeader : Record "Sales Header")
SalesLine.SETCURRENTKEY("Document Type","Document No.","Location Code");
SalesLine.SETRANGE("Document Type","Document Type");
SalesLine.SETRANGE("Document No.","No.");
SalesLine.SETRANGE(Type,SalesLine.Type::Item);
SalesLine.SETRANGE("Drop Shipment",FALSE);
SalesLine.SETRANGE("Job No.",'');
IF SalesLine.FINDFIELDS('-')(“Quantity”, “Location Code”) THEN BEGIN
First := TRUE;
REPEAT
IF (("Document Type" = "Document Type":: Order) AND
(SalesLine.Quantity >= 0)) OR
(("Document Type" = "Document Type"::"Return Order") AND
(SalesLine.Quantity < 0))
THEN
WhseType := WhseType::Outbound
ELSE
WhseType := WhseType::Inbound;
IF First OR (SalesLine."Location Code" <> OldLocationCode) OR
(WhseType <> OldWhseType)
THEN
CreateWhseRqst(SalesHeader,WhseType);
First := FALSE;
OldLocationCode := SalesLine."Location Code";
OldWhseType := WhseType;
UNTIL SalesLine.NEXT = 0;
END;
If we could do something like this it would create a much more defined SQL statement that would much smaller record sizes and much easier to tune for performance because we can create an index with the select list included. This would really benefit situations were a table has a IMAGE datatype that cannot be pulled via an index seek.
SELECT “Quantity”, “Location Code” FROM "CRONUS USA, Inc_$Sales Line" WITH (UPDLOCK) WHERE (("Document Type"=?)) AND (("Document No_"=?)) AND (("Type"=?)) AND (("Drop Shipment"=?)) AND (("Job No_"=?)) ORDER BY "Document Type","Document No_","Location Code","Line No_"
The record size for this statement is 73 bytes with a little index tuning it is 64 bytes.
0
Comments
-
I like the idea of being able to define fields in a query, but I don't think that will work with all the validation code.0
-
You don't need what you wrote.
You only need to set the key-parameter "SQL-Index" of the given key to
"Document No.,Document Type"
so that the sql-server uses this key for its selection.
Listen: The SetCurrentKey in c/side only say's how you want to sort your resultset.
SQL-Performing is very easy in Navision, but you have to know, how the sql-server uses a key for its selection and how it uses a key for order the resultset.
In table 36 or 37 the best key is?
"Document no."
Making a selection! on this key will take:
1 record in table 36
and a maximum of 1000 records in table 37, or does any sales order have more then 1000 lines?
Shure, a selection on table 37 is always more performant when the sql-server has a selection-key with some fields more. But in this case you
only have some milliseconds less.
Your written selection-command will get less bytes, because only the used fields are taken back through the network.
The time you want to perform is not network-traffic. You have to spend the time by making the server faster. You have to help him to be more
performant by its selection and with "order by" in the statement, you wrote, it will not be more performant.
If you want to do your one, why don't you use the MSDAC xxx?
Because you have some performance-problems to merge the result
into navision-table-fields.
What I want for chrismas from Microsoft is only to fix very heavy problems, they exists still since version 4.0!
Greetings
Steve0 -
The point wasn't the sorting order, it was the ability to only select certain fields.0
-
Why?
I think to get more performance, or not?0 -
For one yes, because when you select the columns it would be less network traffic. That's the idea anyway0
-
While we're at it, why don't we just wish they would stop treating SQL like an ISAM database.There are no bugs - only undocumented features.0
-
As long as the C/SIDE platform is still supported, which is an ISAM database, that is not going to happen.0
-
DenSter wrote:As long as the C/SIDE platform is still supported, which is an ISAM database, that is not going to happen.
I agree. This is nothing unique to Navision. Over the years I have worked with a number of products that introduced "SQL" versions. Their approach was just like Navision's. Slap the existing system on top of SQL. The goal was not to create a technically superior product, but to simply allow the salespeople to say "Yes, we run on SQL"There are no bugs - only undocumented features.0 -
Ouch, I cross trained from Sage Line 500 CS/3 on Unix, and it seems I am back at C-ISAM again!Professional Navision Developer0
-
DenSter wrote:The point wasn't the sorting order, it was the ability to only select certain fields.
Could using Linkedobjects solve the problem? (I know it would require a view and a table for each situation, but just for proff of concept...)Regards
Peter0 -
No views have their own weird problems (difficult to update with regular users, you can't test on aC/SIDE database, things like that, not impossible problems but making it difficult to manage), I would not try to solve it that way. Maybe for one or two very specific cases where you'd need to do complicated joins that would work, but I'd stay away from that as a general solution.0
-
DenSter wrote:...I would not try to solve it that way...
Personally I doubt it has any significant improvement on even isolated pieces of code unless the network is extremely slow (WAN), but I have been surprised by the SQL server before :-)Regards
Peter0 -
Nobody wrote:This would really benefit situations were a table has a IMAGE datatype that cannot be pulled via an index seek.Regards
Peter0 -
What NAV does is that it determines if there is an image (BLOB) attached by determining the size.
If the size is large it can cause performance issues.
Bottom line is, try to avoid BLOBs in a SQL database, especialy in Setup tables because it can seriously slow down your SETUP.GET statements.0 -
Mark Brummel wrote:Bottom line is, try to avoid BLOBs in a SQL database, especialy in Setup tables because it can seriously slow down your SETUP.GET statements.
PS: The fact that you answered me the 1st of April and I simply can't believe it, still makes me wonder... :?Regards
Peter0 -
All of this is on a list somewhere in denmark, but it is all about priorities.
The more people ask for a change, the more likely it is implemented.0 -
I'm also longing for a real SELECT although for different reasons. Right now I have to create a report to show stock by Bins and Lots (this is one of the things that should be standard because it's the natural integration of two existing functionality). In SQL it would be as simple as SELECT Bin Code, Lot No., SUM(Quantity) FROM Warehouse Entry GROUP BY Bin Code, Lot No. In Navision? The best idea I managed to come up with is to populate a temp table at the beginning of the report and run on it with the ugly Integer-table solution... clearly a hell of a lot of time wasted on something that's supposed to be simple.0
-
If you are running in SQL Server, you can always create a view, then define that as a table in Navision.
Works really well for reporting.David Machanick
http://mibuso.com/blogs/davidmachanick/0 -
[Topic moved from Upcoming version NAV 5.1 forum to SQL General forum]Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions