I am trying to implement a very fast queue using SQL Server.
The queue table will contain tens of millions of records.
The problem I have is the more records completed, the the slower it
gets. I don't want to remove data from the queue because I use the
same table to store results. The queue handles concurrent requests.
The status field will contain the following values:
0 = Waiting
1 = Started
2 = Finished
Any help would be greatly appreciated.
Here is a simplified script to demonstrate what has been done.
CREATE TABLE [dbo].[Queue] (
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[JobID] [int] NOT NULL ,
[Status] [tinyint] NOT NULL
) ON [PRIMARY]
GO
CREATE INDEX [Status] ON [dbo].[Queue]([Status]) ON [PRIMARY]
GO
CREATE PROCEDURE dbo.NextItem
@JobID integer,
@ID integer output
AS
SELECT TOP 1 @ID = [ID]
FROM Queue WITH (READPAST, XLOCK)
WHERE (Status = 0) AND (JobID = @JobID)
RETURN
GO 6 9112
my idea: i would use 3 different tables, one for waiting entries,
one for the running entries and one for the finished.
And when status is changing instead of updating field "status"
(which is now not longer necessary) move the record from one
table to the other.
hth,
Helmut
"Chris Foster" <ch*********@btinternet.com> schrieb im Newsbeitrag
news:b3*************************@posting.google.co m... I am trying to implement a very fast queue using SQL Server.
The queue table will contain tens of millions of records.
The problem I have is the more records completed, the the slower it gets. I don't want to remove data from the queue because I use the same table to store results. The queue handles concurrent requests.
The status field will contain the following values: 0 = Waiting 1 = Started 2 = Finished
Any help would be greatly appreciated.
Here is a simplified script to demonstrate what has been done.
CREATE TABLE [dbo].[Queue] ( [ID] [int] IDENTITY (1, 1) NOT NULL , [JobID] [int] NOT NULL , [Status] [tinyint] NOT NULL ) ON [PRIMARY] GO
CREATE INDEX [Status] ON [dbo].[Queue]([Status]) ON [PRIMARY] GO
CREATE PROCEDURE dbo.NextItem @JobID integer, @ID integer output AS SELECT TOP 1 @ID = [ID] FROM Queue WITH (READPAST, XLOCK) WHERE (Status = 0) AND (JobID = @JobID) RETURN GO
[posted and mailed, please reply in public]
Chris Foster (ch*********@btinternet.com) writes: The queue table will contain tens of millions of records.
The problem I have is the more records completed, the the slower it gets. I don't want to remove data from the queue because I use the same table to store results. The queue handles concurrent requests.
The status field will contain the following values: 0 = Waiting 1 = Started 2 = Finished ...
CREATE TABLE [dbo].[Queue] ( [ID] [int] IDENTITY (1, 1) NOT NULL , [JobID] [int] NOT NULL , [Status] [tinyint] NOT NULL ) ON [PRIMARY] GO
CREATE INDEX [Status] ON [dbo].[Queue]([Status]) ON [PRIMARY] GO
CREATE PROCEDURE dbo.NextItem @JobID integer, @ID integer output AS SELECT TOP 1 @ID = [ID] FROM Queue WITH (READPAST, XLOCK) WHERE (Status = 0) AND (JobID = @JobID) RETURN GO
Since you have no index on JobID, I am not surprise if this is running
slow beyond all belief. The index you have on Status is likely to be
worthless, not being selective enough.
Helmut Wöss suggested using three tables, and this may be worth considering.
However, you should start with getting a decent index structure. It
is from the table definition unclear to be whether there can be more
than one row for the same JobID. If there is, add a clustered index on
JobID and Status. If JobID is infact unique, get rid of that Identity
column. If your aim is to get high speed, then you should trim the
table, since the smaller the rows, the more rows you can fit on a page,
and the faster you can do I/O.
--
Erland Sommarskog, SQL Server MVP, so****@algonet.se
Books Online for SQL Server SP3 at http://www.microsoft.com/sql/techinf...2000/books.asp
Thank you for your reply
The script I submitted is a smaller sample of what I have. I forgot to
state that the JobID has a foreign key to another table, there will be
many JobIds. Am I correct in assuming that a foreign key is indexed?
I can't set the index to be clustered, because it will only allow one
clustered index, ID is the primary key and is clustered.
The final queue will contain more fields than stated, if this effects
the speed I guess I will have to use a separate queuing table.
My first thought was that if status is indexed and has a value between
0 and 2, the index would be sorted ascending and 0's would be at the
top, therefore would remain the same speed throughout the queue. I am
not sure exactly what indexing does behind the scenes, I should
probably look into this. What difference would it make creating a
composite index of JobID and Status?
Erland Sommarskog <so****@algonet.se> wrote in message news:<Xn*******************@127.0.0.1>... [posted and mailed, please reply in public]
Chris Foster (ch*********@btinternet.com) writes: The queue table will contain tens of millions of records.
The problem I have is the more records completed, the the slower it gets. I don't want to remove data from the queue because I use the same table to store results. The queue handles concurrent requests.
The status field will contain the following values: 0 = Waiting 1 = Started 2 = Finished ...
CREATE TABLE [dbo].[Queue] ( [ID] [int] IDENTITY (1, 1) NOT NULL , [JobID] [int] NOT NULL , [Status] [tinyint] NOT NULL ) ON [PRIMARY] GO
CREATE INDEX [Status] ON [dbo].[Queue]([Status]) ON [PRIMARY] GO
CREATE PROCEDURE dbo.NextItem @JobID integer, @ID integer output AS SELECT TOP 1 @ID = [ID] FROM Queue WITH (READPAST, XLOCK) WHERE (Status = 0) AND (JobID = @JobID) RETURN GO
Since you have no index on JobID, I am not surprise if this is running slow beyond all belief. The index you have on Status is likely to be worthless, not being selective enough.
Helmut Wöss suggested using three tables, and this may be worth considering.
However, you should start with getting a decent index structure. It is from the table definition unclear to be whether there can be more than one row for the same JobID. If there is, add a clustered index on JobID and Status. If JobID is infact unique, get rid of that Identity column. If your aim is to get high speed, then you should trim the table, since the smaller the rows, the more rows you can fit on a page, and the faster you can do I/O.
Hi Chris
If you are after speed and with those sorts of volumes, I would not be
recommending that you used SQL Server to implement a TP queue in the
first place to store requests that are either waiting or started.
There are other options worth considering including IBM WebSphere
MQSeries. ch*********@btinternet.com (Chris Foster) wrote in message news:<b3*************************@posting.google.c om>... I am trying to implement a very fast queue using SQL Server.
The queue table will contain tens of millions of records.
The problem I have is the more records completed, the the slower it gets. I don't want to remove data from the queue because I use the same table to store results. The queue handles concurrent requests.
The status field will contain the following values: 0 = Waiting 1 = Started 2 = Finished
Any help would be greatly appreciated.
Here is a simplified script to demonstrate what has been done.
CREATE TABLE [dbo].[Queue] ( [ID] [int] IDENTITY (1, 1) NOT NULL , [JobID] [int] NOT NULL , [Status] [tinyint] NOT NULL ) ON [PRIMARY] GO
CREATE INDEX [Status] ON [dbo].[Queue]([Status]) ON [PRIMARY] GO
CREATE PROCEDURE dbo.NextItem @JobID integer, @ID integer output AS SELECT TOP 1 @ID = [ID] FROM Queue WITH (READPAST, XLOCK) WHERE (Status = 0) AND (JobID = @JobID) RETURN GO
Chris Foster (ch*********@btinternet.com) writes: The script I submitted is a smaller sample of what I have. I forgot to state that the JobID has a foreign key to another table, there will be many JobIds. Am I correct in assuming that a foreign key is indexed?
No. There are no automatic indexes created on foriegn-key columns. You need
to add any index yourself.
I can't set the index to be clustered, because it will only allow one clustered index, ID is the primary key and is clustered.
On second thought, a non-clustered index on (JobId, Status) is likely
to be ideal. You could add ID explicitly to this index, but it is in fact
already there, because for a non-clustered index, SQL Server uses the
clustered key as the address to the data page.
The point here is that you get a *covering index*, which means that
SQL Server can resolve the query from the index alone. This is good
for speed. Since the index nodes are smaller than the complete rows,
you get more rows per page, and fewer pages to read.
My first thought was that if status is indexed and has a value between 0 and 2, the index would be sorted ascending and 0's would be at the top, therefore would remain the same speed throughout the queue. I am not sure exactly what indexing does behind the scenes, I should probably look into this.
Yes, you should. :-) In a non-clustered index on Status only, SQL
Server needs to go to the data pages to find JobId so it can compare
this condition. This can be a more expensive operation that scanning
the table from left to right, because some pages may have to be read
more than twice. SQL Server uses the statistics is has on Status
to determine whether using the index is a viable way to go. You can
force SQL Server to use the index, by means of an index hint. You may find
that this gives even worse performance.
What difference would it make creating a composite index of JobID and Status?
Because now SQL Server has all the information to resolve the query in
the index.
--
Erland Sommarskog, SQL Server MVP, so****@algonet.se
Books Online for SQL Server SP3 at http://www.microsoft.com/sql/techinf...2000/books.asp
Indexing both JobID and Status has made the queue work at an acceptable speed.
Thanks you
Chris
Erland Sommarskog <so****@algonet.se> wrote in message news:<Xn*********************@127.0.0.1>... Chris Foster (ch*********@btinternet.com) writes: The script I submitted is a smaller sample of what I have. I forgot to state that the JobID has a foreign key to another table, there will be many JobIds. Am I correct in assuming that a foreign key is indexed?
No. There are no automatic indexes created on foriegn-key columns. You need to add any index yourself.
I can't set the index to be clustered, because it will only allow one clustered index, ID is the primary key and is clustered.
On second thought, a non-clustered index on (JobId, Status) is likely to be ideal. You could add ID explicitly to this index, but it is in fact already there, because for a non-clustered index, SQL Server uses the clustered key as the address to the data page.
The point here is that you get a *covering index*, which means that SQL Server can resolve the query from the index alone. This is good for speed. Since the index nodes are smaller than the complete rows, you get more rows per page, and fewer pages to read.
My first thought was that if status is indexed and has a value between 0 and 2, the index would be sorted ascending and 0's would be at the top, therefore would remain the same speed throughout the queue. I am not sure exactly what indexing does behind the scenes, I should probably look into this.
Yes, you should. :-) In a non-clustered index on Status only, SQL Server needs to go to the data pages to find JobId so it can compare this condition. This can be a more expensive operation that scanning the table from left to right, because some pages may have to be read more than twice. SQL Server uses the statistics is has on Status to determine whether using the index is a viable way to go. You can force SQL Server to use the index, by means of an index hint. You may find that this gives even worse performance.
What difference would it make creating a composite index of JobID and Status?
Because now SQL Server has all the information to resolve the query in the index. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: James Radke |
last post by:
Hello,
I have a multithreaded windows NT service application (vb.net 2003) that I
am working on (my first one), which reads a message queue and creates
multiple threads to perform the processing...
|
by: Sinan Nalkaya |
last post by:
hello,
i need a function like that,
wait 5 seconds:
(during wait) do the function
but function waits for keyboard input so if you dont enter any it waits
forever.
i tried time.sleep() but when...
|
by: Jeff Davis |
last post by:
Right now performance isn't a problem, but this question has me curious:
Let's say I have a shopping cart system where there is a "products"
table that contains all possible products, and an...
|
by: rokuingh |
last post by:
ok, so i've been working on this one for quite a while, and the code is very big so i'm just going to give the relevant parts. this is a program that builds polymers (chemical structures of repeated...
|
by: Hemant Shah |
last post by:
Folks,
I am having problem with an application that uses static SQL,
the application basically browses through the table given start and
end key most of the time it is processed from begining to...
| |
by: jonathan184 |
last post by:
Hi I am trying to access a log file and read the fikle into an array and split the file using the space as a delimiter but i get this error.
Parse error: syntax error, unexpected $end in...
|
by: Spoon |
last post by:
Hello,
I'm wondering whether the STL defines a data structure with
the following features:
o provides push_front() and pop_back() (like std::list) to
implement a FIFO buffer.
o allows fast...
|
by: LanaR |
last post by:
Hello,
one sql statement is causing severe performance issue. The problem occurs only in UDB environment, the same statemnt on the mainframe is running fine. I have an explain output from the sql....
|
by: Krzysztof Retel |
last post by:
Hi guys,
I am struggling writing fast UDP server. It has to handle around 10000
UDP packets per second. I started building that with non blocking
socket and threads. Unfortunately my approach...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
| |
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
| |