Why is my simple SQL statement taking so long to execute and how do i go about finding the issue? - sql

I have a very simple SQL query:
select o.Visit_ID
from Datamart.dbo.ww_Orders o
inner join Datamart.dbo.ww_Order_Details on o.Visit_ID = ww_Order_Details.Visit_ID
where o.runstamp = '20160422'
this query takes < 0 seconds to return 11173 rows
When I add the GROUP BY statement:
select o.Visit_ID
from Datamart.dbo.ww_Orders o
inner join Datamart.dbo.ww_Order_Details on o.Visit_ID = ww_Order_Details.Visit_ID
where o.runstamp = '20160422'
group by o.Visit_ID
the server takes 6min 30 sec to retrieve the 3047 rows.
I would expect the GROUP BY query to take not that much longer than the original. How do I go about finding what the issues are? thanks
here are the table definitions:
Orders:
CREATE TABLE [dbo].[ww_Orders](
[Visit_ID] [int] NOT NULL,
[Member_ID] [int] NOT NULL,
[Membership_no] [varchar](20) NULL,
[Member_Card_Num_Orig] [varchar](16) NULL,
[SCV_ID] [int] NULL,
[Meeting_No] [int] NULL,
[Location_Name] [varchar](128) NULL,
[Leader_No] [int] NULL,
[CashAmt] [decimal](18, 2) NULL,
[EFTAmt] [decimal](18, 2) NULL,
[VouchAmt] [decimal](18, 2) NULL,
[Meet_Date] [datetime] NULL,
[runstamp] [varchar](50) NULL,
CONSTRAINT [PK_dbo.ww_Orders] PRIMARY KEY CLUSTERED
(
[Visit_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
Order Details:
CREATE TABLE [dbo].[ww_Order_Details](
[ord_det_pk] [int] IDENTITY(1,1) NOT NULL,
[Visit_ID] [int] NOT NULL,
[Item_Code] [nvarchar](50) NULL,
[Item_Name] [nvarchar](50) NULL,
[Qty] [int] NULL,
[Amt] [decimal](18, 2) NULL,
[Category_Code] [nvarchar](20) NULL,
CONSTRAINT [PK_ww_Order_Details] PRIMARY KEY CLUSTERED
(
[ord_det_pk] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[ww_Order_Details] WITH CHECK ADD CONSTRAINT [FK_ww_Order_Details_ww_Orders] FOREIGN KEY([Visit_ID])
REFERENCES [dbo].[ww_Orders] ([Visit_ID])
GO
ALTER TABLE [dbo].[ww_Order_Details] CHECK CONSTRAINT [FK_ww_Order_Details_ww_Orders]
GO

I'd add an index onto ww_Order_Details Visit_ID, probably make it the clustered index and drop the index on ord_det_pk. Also it might make more sense as an exists?
select o.Visit_ID
from Datamart.dbo.ww_Orders o
where exists (select 0 from Datamart.dbo.ww_Order_Details where o.Visit_ID = ww_Order_Details.Visit_ID)
and o.runstamp = '20160422'

I usually try to use a common table expression in cases like these, when a part of the query is really fast but an addition of a simple operation makes it really slow, usually it helps.
Try:
WITH CTE AS (
select o.Visit_ID
from Datamart.dbo.ww_Orders o
inner join Datamart.dbo.ww_Order_Details od on o.Visit_ID = od.Visit_ID
where o.runstamp = '20160422'
)
SELECT Visit_ID FROM CTE
group by Visit_ID
If this helps you can try to compare execution plans for your original query and this version to see whats going on

Related

Performance issue with geometry table in SQL Server

I am on SQL Server 11. I have the following table that stores the boundary of all LGA in NSW
CREATE TABLE [dbo].[nsw_lga_polygon_shp](
[id] [int] IDENTITY(1,1) NOT NULL,
[geom] [geometry] NULL,
[lg_ply_pid] [nvarchar](15) NULL,
[dt_create] [date] NULL,
[dt_retire] [date] NULL,
[lga_pid] [nvarchar](15) NULL,
[nsw_lga_sh] [date] NULL,
[nsw_lga__1] [date] NULL,
[nsw_lga__2] [nvarchar](100) NULL,
[nsw_lga__3] [nvarchar](100) NULL,
[nsw_lga__4] [date] NULL,
[nsw_lga__5] [nvarchar](15) NULL,
CONSTRAINT [PK_nsw_lga_polygon_shp] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
END
GO
SET IDENTITY_INSERT [dbo].[nsw_lga_polygon_shp] ON;
The table only have 198 rows
When I try to map the result against one of my table that have 36,531 rows, I notice that it have very serious performance issue, it told 5 mins to generate 500 rows.
select
* ,
(select top 1
nsw_lga__2
from
[nsw_lga_polygon_shp]
where
Geom.Filter(geometry::STGeomFromText('point(' +
convert(varchar(100),longitude_GIS )+
' ' +
cast(latitude_GIS as varchar(100))+ ')',4283)) = 1
) LGA
from
Report_A
Is there anyway I can may it run faster? Can I index the geometry column?
Thanks in advance!

Sql server database store procedure query

I have two tables as below:
1) UserFavouriteCurrencies
CREATE TABLE [dbo].[UserFavouriteCurrencies](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[UserId] [int] NULL,
[CurrencyId] [int] NULL,
[EntryDate] [datetime] NULL,
CONSTRAINT [PK_UserFavouriteCurrencies] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Above table is holding data of user favorite companies
2) CurrencyRates
CREATE TABLE [dbo].[CurrencyRates](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[CurrencyId] [int] NULL,
[Price] [float] NULL,
[Open_24h] [float] NULL,
[Volume_24h] [float] NULL,
[Low_24h] [float] NULL,
[High_24h] [float] NULL,
[Volume_30d] [float] NULL,
[BestBid] [float] NULL,
[BestAsk] [float] NULL,
[TradeId] [bigint] NULL,
[PriceDate] [datetime] NULL,
[PriceDateTimestamp] [bigint] NULL,
[OpenInterest] [float] NULL,
CONSTRAINT [PK_CoinbaseTickerRatesMaster] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Above table holds rates details of currencies.
Call : EXEC sp_Getdata 1(Here 1 in UserId of UserFavouriteCurrencies table)
I need all records for particular currencies last latest records in one query as below
DECLARE #Today DATETIME = GETDATE(), #PrevDate DATETIME = GETDATE()<br>
SELECT TOP 1 Price, PriceDate, Volume_24h, PriceDateTimestamp
FROM CurrencyRates
WHERE CurrencyId = #CurrencyId AND PriceDate <= #Today
ORDER BY PriceDateTimestamp DESC
Above query is only select data for one particular currency but I need the data related to user which added on UserFavouriteCurrencies table.
Please help me to write store procedure for this query
Thanks in advance.
For each currency in UserFavouriteCurrencies Table, consider the query below
SELECT
uc.Id -- This is the userId
,cr.Price
,cr.PriceDate,
,cr.Volume_24h
,cr.PriceDateTimestamp
FROM
UserFavouriteCurrencies AS uc
INNER JOIN CurrencyRates AS cr -- See Hints : 1
ON cr.CurrencyId = uc.CurrencyId
WHERE
PriceDate <= GETDATE()
AND
uc.Id = #Id
-- You can add other Predicates Here...
Hints:
Consider using LEFT OUTER JOIN if user's currency may not exist in CurrencyRates
!This will however introduce NULLs which you must handle

Join multiple tables based on date range selected

I have tables stored per month. And each month contains about half a million rows.
I want to allow my application user to select any date range they choose and dynamically join the appropriate tables. The range could be within one table or several tables.
Please suggest the best way to go about this.
Some table names:
sqlt_data_1_2014_01
sqlt_data_1_2014_02
sqlt_data_1_2014_03
sqlt_data_1_2014_04
sqlt_data_1_2014_05
sqlt_data_1_2014_06
...etc
One table definition:
CREATE TABLE [dbo].[sqlt_data_1_2014_06]
( [tagid] [int] NOT NULL,
[intvalue] [bigint] NULL,
[floatvalue] [float] NULL,
[stringvalue] [varchar](255) NULL,
[datevalue] [datetime] NULL,
[dataintegrity] [int] NULL,
[t_stamp] [bigint] NOT NULL,
PRIMARY KEY CLUSTERED ([tagid] ASC, [t_stamp] ASC)
WITH( PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Date time index sql server 2005

I know this is a common topic but i stil feel my scenario requires some custom advice. I was selecting from a table the other day and it took me an AGE to select on a datetime column that has not been indexed. I want to index this, only problem ebing is that the "production" 2005 box i am unfamiliar with and how it will handle the index creation. With that in mind i am wondering what the safest way for me to create an index on the table is. All the details i think people will need are below (i hope) :
Index to be created on field 5 (possibly field4 also)
Table 1 definition:
CREATE TABLE [dbo].[TABLE 1](
[ID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_BLA] DEFAULT (newid()),
[field1] [nvarchar](7) NULL,
[field2] [nvarchar](10) NULL,
[field3] [nvarchar](2) NULL,
[field4] [datetime] NULL,
[field5] [datetime] NULL,
[field6] [smallint] NULL,
[field7] [nvarchar](1) NULL,
[field8] [nvarchar](7) NULL,
[field9] [nvarchar](60) NULL,
[field10] [smallint] NULL,
[field11] [nvarchar](15) NULL,
[field12] [datetime] NULL,
CONSTRAINT [PK_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Total count of rows in Table 1 : 2926836

Managing multiple users getting work assignments in SQL Server 2008R2

I have a SQL database that has two tables that hold a queue of work to be done and the history of that work:
CREATE TABLE [dbo].[WorkQueue](
[WorkQueueID] [int] IDENTITY(1,1) NOT NULL,
[BatchID] [int] NOT NULL,
[AdHocProjectID] [int] NOT NULL,
[TaskID] [int] NOT NULL,
[CreateDate] [datetime] NOT NULL,
[CompletedDate] [datetime] NULL,
[AlertMessage] [varchar](1024) NULL,
CONSTRAINT [PK_WorkQueue] PRIMARY KEY CLUSTERED
(
[WorkQueueID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[WorkQueueHistory](
[WorkQueueHistoryID] [int] IDENTITY(1,1) NOT NULL,
[WorkQueueID] [int] NOT NULL,
[EmployeeID] [int] NOT NULL,
[BatchBoxID] [int] NOT NULL,
[StartTime] [datetime] NOT NULL,
[EndTime] [datetime] NULL,
[PercentageCompleted] [int] NOT NULL,
[FinishedTask] [bit] NOT NULL,
[comment] [varchar](255) NULL,
CONSTRAINT [PK_WorkQueueHistory] PRIMARY KEY CLUSTERED
(
[WorkQueueHistoryID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
The WorkQueue table contains tasks from batches (Jobs) that need to be worked. Users insert into the WorkQueueHistory table when they start working on a job, and when they finish working on a job that row in the WorkQueueHistory table is updated with their end time and the FinishedTask bit is set if that task was indeed completed 100%.
My question is what is the best way to prevent two users from starting the same task? Right now we don't have enough users for this to be a problem, but as things grow I know there is going to be a concurrency issue if I don't address this.
You should use a transaction with the appropriate isolation level set.
See http://www.blackwasp.co.uk/SQLTransactions.aspx
begin tran
-- select next job to do
-- update job as started
commit