I see this topic debated from time to time. People who spend a fair amount of time writing queries against the Prophet 21 database are sometimes confused between using the views and writing queries directly against the tables. Most of the time the standard answer I see is “Always use the Prophet 21 views”. It’s my humble opinion that the answer to a question like this rarely begins with the words ‘always’ or ‘never’. Like many things related to Prophet 21, my answer to this question is “it depends”. I tend to believe that there is a time and place for both methods and this post will be a deep dive on my thoughts on how to approach the issue in an objective manner.
What is NOLOCK?
NOLOCK is a table hint in the SQL Server database system. Table hints change how the query analyzer behaves during the execution of the query. A table hint only lasts for the execution of the SQL statement. Additionally, table hints only apply to the table that they are hinting against. If you want to use a table hint on multiple tables, it must be specified for each table.
READUNCOMMITTED both serve the exact same purpose. The purpose of the hint is to allow a “dirty read”. A dirty read, means that the query runs without placing a shared lock on the accessed data. Also, locks on the data by other transactions do not prevent the query from running.
Pros of NOLOCK
The biggest advantage of
NOLOCK is speed and concurrency. Ignoring data locks during query execution eliminates the wait time associated with other transactions that touch the same data. The other major plus is that you need not worry about your query deadlocking the database other users having what will feel like a Prophet 21 lock up. Have you ever executed a big, expensive query on the invoice header table and seconds later, someone in Accounting calls the help desk because his session is locked? Guess what, you have just experienced a deadlock.
Cons of NOLOCK
NOLOCK does have a big drawback. Because locks are ignored, there is a chance that the data you read may be inconsistent. For example, let’s say you are reading inventory data with the
NOLOCK table hint at the same time that a large adjustment is being imported into Prophet 21. Since you are not waiting for the import to complete, your query will not account for the changes to the data that are caused by the import.
Prophet 21 Views Explained
Prophet 21 ships with many SQL views that aid in query development. Though not always true, these queries often begin with a prefix that reads
p21_view. In some cases, the P21 query simply selects the table with the
NOLOCK table hint. In other cases, the view contains one or more joined tables to provide commonly accessed fields to the query.
EXAMPLE 1: “p21_view_inv_loc”
In this example, we will review the
p21_view_inv_loc predefined view to analyze how it is built and what it does.
SELECT dbo.inv_loc.location_id, ...[remaining inv_loc fields].... ,dbo.inv_loc.slab_track_bins_flag , dbo.inv_loc.edi_832_discontinued_sent_flag , dbo.inv_mast.item_id FROM dbo.inv_loc WITH (NOLOCK) INNER JOIN dbo.inv_mast WITH (NOLOCK) ON dbo.inv_mast.inv_mast_uid = dbo.inv_loc.inv_mast_uid
The structure of the view joins in the
inv_mast table for the purpose of putting the
item_id field into the query. This is a very simple, basic predefined view, suitable for use in most queries. It is not really expensive, and chances are, since it is so simple, using it often will not cause any problems.
Example 2: “p21_view_invoice_line”
This example looks at another seemingly simple view…
SELECT ...[columns]... FROM dbo.invoice_line WITH (NOLOCK) INNER JOIN dbo.invoice_hdr WITH (NOLOCK) ON dbo.invoice_hdr.invoice_no = dbo.invoice_line.invoice_no LEFT OUTER JOIN dbo.currency_line WITH (NOLOCK) ON dbo.currency_line.currency_line_uid = dbo.invoice_hdr.currency_line_uid
This view is a little more complex. There are joins back to the
invoice_hdr table and a left join back to the
currency_line table. There are also 7
CASE statements in the view. Clearly there is more going on meets the eye.
Choosing a Method
Ad Hoc Queries for Prophet 21
I typically classify queries in 2 major camps. The first camp are ad hoc queries I am only using for a short period of time. This usually happens when a project requires a rather quick custom dump of data or something similar. In other words, this query see production use on an ongoing basis. In an ad hoc query, I almost always use the Prophet 21 predefined views. The development time is a little faster, and I do not have any real concern worrying over the speed of the query. Finally, an ad hoc query, by its very nature, gets thrown away, so why obsess over it?
Queries for Production Use
By contrast, the second class of query, obviously, is a query that will be put into daily use to drive some extended functionality or reporting. This includes queries used to drive add-on applications, DynaChange business rules, or SQL Reporting Services reports. For these queries, I also give weight to how often I expect the query to run in production.
As a query becomes more complex and/or more often used, I spend more time tuning it. Tuning the query serves the dual purpose of reducing stress on the database and improving the user’s perception of speed and performance. For instance, if I am working with the
inv_loc table and I need more than just
item_id from inv_mast, then using the predefined view doesn’t make sense to me. It is the same thing as joining the
inv_mast table into the query twice. This adds extra cost that the query doesn’t benefit from.
There have been multiple instances where I used a Prophet 21 view and found that the majority of cost in the execution plan came from the view itself. This happened due to either additional table joins or a strange, costly index access that slowed everything down. Removing the view and using the table with a
NOLOCK hint dramatically improved query performance. This happened on several queries that worked with invoice related tables.
Rolling without NOLOCK in Prophet 21
Most queries I write are at a very low risk of being affected by a read without locking. Typically, the query looks at historical data, not normally subject to changes. Additionally, the decisions made from the subject data tolerate a little bit of variance without issue.
There may be some instances though where uncommitted data must be accounted for or the query reads data that changes in real-time. As a result, those cases may require queries against the tables without a
NOLOCK hint. These happen to me so infrequently that I cannot recall the last time I needed to do it. Ususally, managing the expectations of the user suffices to allow for putting in the
NOLOCK hint. Should you choose to roll without this hint, beware that you query is subject to deadlocking and may affect other users. If you have a slow, expensive query that does not use a view or
NOLOCK, it is best to run it during low usage hours. This reduces the chance of a deadlock affecting other users.
Summing it all up, as I stated early on, the answer is “it depends”. While there is no hard rule for you to use a certain method, selecting carefully can greatly improve system performance. I also recommend looking at execution plans for complex queries, especially when using Prophet 21 views. At the very least, you have the chance to look for problems that may reveal themselves in the form of a slow running app or report.
Read More about Prophet 21 on freeingerp.com