Quantcast
Channel: dBforums – Everything on Databases, Design, Developers and Administrators
Viewing all articles
Browse latest Browse all 13329

Slow down with multiple users

$
0
0
I currently have a database that handles inventory control with consignment and billing that when 2 users run their front end files one of them slows down a second to easily 10-15 seconds depending on the data being returned. The database is instantaneous when only one user is accessing the file.

Running office 2007 on all the pcs with them all being up to date with microsoft updates.
Currently the database is split with each using having their own front end accde file.
I also have a persistent connection setup on my main menu in the record source. The main menu cannot be closed without completely terminating access.
Currently all users access the file via a VPN but I have tried putting it on the local network on server grade hardware and is still slows down with 2 people accessing the file.

The big issue I have run into is combo box that is used to select items is extremely slow with multiple users. This combo box returns currently 1321 records. I have the combo box set as a snapshot. The bound column is set to 3. I have an index setup on the Subcategory and Product columns in the table.

The query for the combo box is:
Code:

SELECT [Subcategory] & "-" & [Productname] AS Product, tblProductCategory.Category, tblProduct.ProductID, tblProduct.ListPrice, tblProduct.PackagedBy, AvailableTotal([ProductID]) AS [Qty Available]
FROM tblProductSubCategory INNER JOIN (tblProductCategory INNER JOIN tblProduct ON tblProductCategory.CategoryID = tblProduct.CategoryID) ON tblProductSubCategory.SubcategoryID = tblProduct.SubcategoryID
WHERE (((tblProduct.Discontinued)=0)) OR ((([Forms]![frmOrder].[txtStatusID])>=4))
ORDER BY tblProductSubCategory.Subcategory, tblProduct.ProductName;

I have an index setup on all the dates columns in the tables. Below code is modified from allenbrowne's inventory calculation from here Allen Browne - Inventory Control: Quantity on Hand

The module code to generate the Qty Available is
Code:

Option Compare Database
Option Explicit

Function AvailableTotal(vProductID As Variant, Optional vAsOfDate As Variant) As Long
'Purpose:  Return the quantity-on-hand for a product.
'Arguments: vProductID = the product to report on.
'          vAsOfDate  = the date at which quantity is to be calculated.
'                          If missing, all transactions are included.
'Return:    Quantity on hand. Zero on error.
    Dim db As DAO.Database          'CurrentDb()
    Dim rs As DAO.Recordset        'Various recordsets.
    Dim lngProduct As Long          'vProductID as a long.
    Dim strAsOf As String          'vAsOfDate as a string.
    Dim strSTDateLast As String    'Last Stock Take Date as a string.
    Dim strDateClause As String    'Date clause to use in SQL statement.
    Dim strSQL As String            'SQL statement.
    Dim lngQtyLast As Long          'Quantity at last stocktake.
    Dim lngQtyAcq As Long          'Quantity acquired since stocktake.
    Dim lngQtyUsed As Long          'Quantity used since stocktake.
    Dim lngQtyRet As Long          'Quantity returned since stocktake
    Dim lngQtySmallUsed As Long    'Quantity used for small orders since stocktake
    Dim lngQtyOrder As Long        'Quantity on order since stockdate

    If Not IsNull(vProductID) Then
        'Initialize: Validate and convert parameters.
        Set db = CurrentDb()
        lngProduct = vProductID
        If IsDate(vAsOfDate) Then
            strAsOf = "#" & Format$(vAsOfDate, "mm\/dd\/yyyy") & "#"
        End If

        'Get the last stocktake date and quantity for this product.
        If Len(strAsOf) > 0 Then
            strDateClause = " AND (StockTakeDate <= " & strAsOf & ")"
        End If
        strSQL = "SELECT TOP 1 StockTakeDate, Quantity FROM tblProductStock " & _
                "WHERE ((ProductID = " & lngProduct & ")" & strDateClause & _
                ") ORDER BY StockTakeDate DESC;"

        Set rs = db.OpenRecordset(strSQL)
        With rs
            If .RecordCount > 0 Then
                strSTDateLast = "#" & Format$(!StockTakeDate, "mm\/dd\/yyyy") & "#"
                lngQtyLast = Nz(!Quantity, 0)
            End If
        End With
        rs.Close

        'Build the Date clause
        If Len(strSTDateLast) > 0 Then
            If Len(strAsOf) > 0 Then
                strDateClause = " Between " & strSTDateLast & " And " & strAsOf
            Else
                strDateClause = " >= " & strSTDateLast
            End If
        Else
            If Len(strAsOf) > 0 Then
                strDateClause = " <= " & strAsOf
            Else
                strDateClause = vbNullString
            End If
        End If

        'Get the quantity acquired since then.
        strSQL = "SELECT Sum(tblVendorOrderDetail.QuantityReceived) AS QuantityAcq " & _
                "FROM tblVendorOrder INNER JOIN tblVendorOrderDetail ON tblVendorOrder.OrderID = tblVendorOrderDetail.OrderID " & _
                "WHERE ((tblVendorOrderDetail.ProductID = " & lngProduct & ")) AND ((tblVendorOrderDetail.PostInventory) = -1"
        If Len(strDateClause) = 0 Then
            strSQL = strSQL & ");"
        Else
            strSQL = strSQL & " AND (tblVendorOrderDetail.DateReceived " & strDateClause & "));"
        End If

        Set rs = db.OpenRecordset(strSQL)
        If rs.RecordCount > 0 Then
            lngQtyAcq = Nz(rs!QuantityAcq, 0)
        End If
        rs.Close

        'Get the quantity Ordered since then.
        strSQL = "SELECT Sum(tblVendorOrderDetail.QuantityOrdered) AS QuantityOrder " & _
                "FROM tblVendorOrder INNER JOIN tblVendorOrderDetail ON tblVendorOrder.OrderID = tblVendorOrderDetail.OrderID " & _
                "WHERE ((tblVendorOrderDetail.ProductID = " & lngProduct & ")) AND ((tblVendorOrderDetail.PostInventory) = 0"
        If Len(strDateClause) = 0 Then
            strSQL = strSQL & ");"
        Else
            strSQL = strSQL & " AND (tblVendorOrder.OrderedDate " & strDateClause & "));"
        End If

        Set rs = db.OpenRecordset(strSQL)
        If rs.RecordCount > 0 Then
            lngQtyOrder = Nz(rs!QuantityOrder, 0)
        End If
        rs.Close

        'Get the quantity returned since then
        strSQL = "SELECT Sum(tblReturnDetail.QuantityReturned) AS QuantityRet " & _
                "FROM tblReturn INNER JOIN tblReturnDetail ON tblReturn.ReturnID = tblReturnDetail.ReturnID " & _
                "WHERE (tblReturnDetail.ProductID = " & lngProduct & ") AND ((tblReturnDetail.QuantityReturned) Is Not Null"
        If Len(strDateClause) = 0 Then
            strSQL = strSQL & ");"
        Else
            strSQL = strSQL & " AND (tblReturn.ReturnDate " & strDateClause & "));"
        End If

        Set rs = db.OpenRecordset(strSQL)
        If rs.RecordCount > 0 Then
            lngQtyRet = Nz(rs!QuantityRet, 0)
        End If
        rs.Close

        'Get the quantity used in orders since then.
        strSQL = "SELECT Sum(tblOrderDetail.Quantity) AS QuantityUsed " & _
                "FROM tblOrder INNER JOIN tblOrderDetail ON " & _
                "tblOrder.OrderID = tblOrderDetail.OrderID " & _
                "WHERE ((tblOrderDetail.ProductID = " & lngProduct & ")"
        If Len(strDateClause) = 0 Then
            strSQL = strSQL & ");"
        Else
            strSQL = strSQL & " AND (tblOrder.OrderDate " & strDateClause & "));"
        End If

        Set rs = db.OpenRecordset(strSQL)
        If rs.RecordCount > 0 Then
            lngQtyUsed = Nz(rs!QuantityUsed, 0)
        End If
        rs.Close

        'Get the quantity used in small orders since then.
        strSQL = "SELECT Sum(tblOrderSmallDetail.Quantity) AS QuantitySmallUsed " & _
                "FROM tblOrderSmall INNER JOIN tblOrderSmallDetail ON " & _
                "tblOrderSmall.SmallOrderID = tblOrderSmallDetail.SmallOrderID " & _
                "WHERE ((tblOrderSmallDetail.ProductID = " & lngProduct & ")"
        If Len(strDateClause) = 0 Then
            strSQL = strSQL & ");"
        Else
            strSQL = strSQL & " AND (tblOrderSmall.OrderDate " & strDateClause & "));"
        End If
        Set rs = db.OpenRecordset(strSQL)
        If rs.RecordCount > 0 Then
            lngQtySmallUsed = Nz(rs!QuantitySmallUsed, 0)
        End If
        rs.Close

        'Assign the return value
        AvailableTotal = lngQtyLast + lngQtyAcq + lngQtyRet + lngQtyOrder - lngQtyUsed - lngQtySmallUsed
    End If

    Set rs = Nothing
    Set db = Nothing
    Exit Function
End Function

Does anyone have any idea on how I can improve on these queries or improve the database overall. All my research so far shows that I have done everything I can to optimize these queries but still is extremely slow with just 2 users.

Viewing all articles
Browse latest Browse all 13329

Trending Articles