Sybase ASE fetching millions of rows is slow - sql

A query on Sybase tables takes a long time to fetch when the returned row count is in the millions. Execution is fast with indexes, but fetch is slow. What are some ideas to improve the performance of the fetch?
The three tables are similar to:
CREATE TABLE Table1{ // data
commonCol1 varchar(50),
table1Col1 float,
table1Col2 varchar(50),
table1Col3 int default 0,
commonCol3 DATE,
PRIMARY KEY (commonCol1, commonCol3)
}
CREATE INDEX index1 ON Table1(commonCol1, table1Col1, table1Col2, table1Col3, commonCol3)
CREATE TABLE Table2{ // dep
commonCol2 varchar(50),
table2Col1 int default 0,
commonCol3 DATE,
PRIMARY KEY (commonCol2, commonCol3)
}
CREATE INDEX index2 ON Table2(commonCol2, table2Col1, commonCol3)
CREATE TABLE Table3 { // join
commonCol1 varchar(50),
commonCol2 varchar(50),
commonCol3 DATE,
PRIMARY KEY (commonCol1, commonCol2, commonCol3)
}
CREATE INDEX index3 ON Table3(commonCol1, commonCol2, commonCol3)
The query is:
CREATE PROCEDURE dbo.myProc #val1 varchar(50), #val2 varchar(50)
AS BEGIN
SELECT Table3.commonCol1, Table1.table1Col1, Table1.table1Col3 FROM Table3
INNER JOIN Table1 ON Table1.commonCol1 = Table3.commonCol1
INNER JOIN Table2 ON Table2.commonCol2 = Table3.commonCol2
WHERE Table1.table1Col2 = #val1 AND Table1.commonCol3 = CONVERT(DATE, #val2) AND Table2.commonCol3 = CONVERT(DATE, #val2) AND Table3.commonCol3 = CONVERT(DATE, #val2)
GROUP BY Table3.commonCol1, Table1.table1Col1, Table1.table1Col3
HAVING MIN( Table2.table2Col1 ) = 1 AND ( MAX( Table1.table1Col3 ) <=1 OR MIN( ABS ( ROUND( Table1.table1Col1, 4) ) ) > 0 )
END

Related

How do I limit the number of ROWS being returned in my SQL Server Function?

CREATE FUNCTION [dbo].[GET_CUSTOMER_DATA]
(
-- Add the parameters for the function here
#customerID bigint,
#maxRows int,
#offset int,
#rows int
)
RETURNS TABLE
AS
RETURN
(
-- Add the SELECT statement with parameter references here
SELECT *
FROM SS_CustomerCard AS SS_CC
INNER JOIN SS_PersonalRepresentative AS SS_PR
ON SS_PR.customerID = SS_CC.ID
INNER JOIN SS_ApplicationStatus AS SS_AS
ON SS_AS.CustomerID = SS_CC.ID
WHERE
SS_CC.ID='#customerID'
ORDER BY SS_AS.EventDateTime DESC, SS_CC.FirstName DESC, SS_CC.LastName DESC
OFFSET #offset ROWS
FETCH NEXT #rows ROWS ONLY
)
GO
I want to pass a parameter to limit the number of rows being returned (maxRows)
You can use the TOP() clause in the SELECT statement.
Here is a conceptual example.
SQL
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, vehicleMake VARCHAR(20));
INSERT INTO #tbl (vehicleMake) VALUES
('Chevrolet'),
('Tesla'),
('Audi'),
('Nissan');
DECLARE #tableVariable TABLE (ID INT, vehicleMake VARCHAR(20));
DECLARE #topRows INT = 2;
INSERT INTO #tableVariable
SELECT *
FROM #tbl
ORDER BY id;
SELECT TOP(#topRows) *
FROM #tableVariable
ORDER BY id;
I think you are trying to limit the total number of rows BEFORE the OFFSET/FETCH. If so, you need to put it in a subquery/derived table, and add another ORDER BY:
CREATE FUNCTION [dbo].[GET_CUSTOMER_DATA]
(
-- Add the parameters for the function here
#customerID bigint,
#maxRows int,
#offset int,
#rows int
)
RETURNS TABLE
AS
RETURN
(
SELECT *
FROM (
SELECT TOP (#maxRows) all_needed_columns_here_aliased_if_necessary
FROM SS_CustomerCard AS SS_CC
INNER JOIN SS_PersonalRepresentative AS SS_PR
ON SS_PR.customerID = SS_CC.ID
INNER JOIN SS_ApplicationStatus AS SS_AS
ON SS_AS.CustomerID = SS_CC.ID
WHERE
SS_CC.ID=#customerID
ORDER BY SS_AS.EventDateTime DESC, SS_CC.FirstName DESC, SS_CC.LastName DESC
) t
ORDER BY EventDateTime DESC, FirstName DESC, LastName DESC
OFFSET #offset ROWS
FETCH NEXT #rows ROWS ONLY
)
GO

Updating 20 rows in a table is really slow

I can't figure out why updating only 21 rows in a table takes so much time.
Step 1: I'm creating #tempTable from the StagingTable (it will never have more than 20 rows of data)
CREATE TABLE #tmpTable (
ID INT NULL,
UniqueID INT NULL,
ReportDate VARCHAR(15) NULL,
DOB Datetime NULL,
Weight VARCHAR(15) NULL,
Height VARCHAR(15) NULL)
INSERT INTO #tempTable (
ID,
UniqueID,
ReportDate,
DOB,
Weight,
Height)
SELECT
A.ID,
A.UniqueID,
A.ReportDate,
A.DOB,
A.Weight,
A.Height
FROM [testDB].[StagingTable] as A
WHERE A.UniqueID = '12345'
Step 2. Updating FinalTable:
UPDATE [Customers].[FinalTable]
SET ID = B.ID,
UniqueID = B.UniqueID,
ReportDate = B.ReportDate,
DOB = B.DOB,
Weight = B.Weight,
Height = B.Height
FROM #tempTable AS B
WHERE [Customers].[FinalTable].[ReportDate] = B.ReportDate
AND [Customers].[FinalTable].[DOB] = B.DOB
This query takes more than 30 minutes!
Is there any way to speed up this update process? Any ideas what I might be doing wrong?
I just want to add that the FinalTable has millions of rows...
Any help would be greatly appreciated.
Thanks!
If there are only 30 matches, then you want an index on #temptable(ReportDate, DOB):
create index idx_temptable_2 on #temptable(ReportDate, DOB);

Why Optimizer Does Not Use Index Seek on Join

I wonder why the following SELECT statement (below) does not use Index Seek, but Index Scan. Is it just because the number of rows is too small or am I missing something?
Test data:
-- Init Tables
IF OBJECT_ID ( 'tempdb..#wat' ) IS NOT NULL
DROP TABLE #wat;
IF OBJECT_ID ( 'tempdb..#jam' ) IS NOT NULL
DROP TABLE #jam;
CREATE TABLE #wat (
ID INT IDENTITY(1,1) NOT NULL,
Name VARCHAR(15) NOT NULL,
Den DATETIME NOT NULL
)
CREATE TABLE #jam (
ID INT IDENTITY(1,1) NOT NULL,
Name VARCHAR(15) NOT NULL
)
-- Populate Temp Tables with Random Data
DECLARE #length INT
,#charpool VARCHAR(255)
,#poolLength INT
,#RandomString VARCHAR(255)
,#LoopCount INT
SET #Length = RAND() * 5 + 8
SET #CharPool = 'abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789'
SET #PoolLength = LEN(#CharPool)
SET #LoopCount = 0
SET #RandomString = ''
WHILE (#LoopCount < 500)
BEGIN
INSERT INTO #jam (Name)
SELECT SUBSTRING(#Charpool, CONVERT(int, RAND() * #PoolLength), 5)
SET #LoopCount = #LoopCount + 1
END
-- Insert Rows into Second Temp Table
INSERT INTO #wat( Name, Den )
SELECT TOP 50 Name, GETDATE()
FROM #jam
-- Create Indexes
--DROP INDEX IX_jedna ON #jam
--DROP INDEX IX_dva ON #wat
CREATE INDEX IX_jedna ON #jam (Name) INCLUDE (ID);
CREATE INDEX IX_dva ON #wat (Name) INCLUDE (ID, Den);
-- Select
SELECT *
FROM #jam j
JOIN #wat w
ON w.Name = j.Name
Execution Plan:
There are several ways for optimiser to do jons: nested loops, hash match or merge join (your case) and may be another.
In dependence of your data: count of rows, existed indexes and statistics id decides which one is better.
in your example optimiser assumes that there is many-to-many relation. And you have both tables soret(indexed) by this fields.
why merge join? - it is logically - to move through both tables parallel. And server will have to do that only once.
To make seek as you want, the server have to move thorugh first table once, and have to make seeks in second table a lot of times, since all records have matches in another table. Server will read all records if he seeks. And there no profit when using seek (1000 seeks even more difucult than one simple loop through 1000 records).
if you want seek add some records with no matches and where clause in your query.
UPD
even adding simple
where j.ID = 1
gives you seek

How to use equal and not equal together in SQL Server

I have to select values from three tables. First table is sale_project_detail, the second table is design_project_detail, and the third table is design_designer.
sale_project_detail schema:
Id int,
Name nvarchar(50),
ShortDescription nvarchar(max)
design_project_assignment schema:
Id int,
DId int (It is foreign key of design_designer table),
SPId int (It is foreign key of sale_project_detail table),
AssignDateTime datetime,
DueDate date,
Status varchar(10)
design_designer schema:
Id int,
Name nvarchar(15)
Now, I have to select complete detail from sale_project_detail
where assign_project_detail.SPId <> sale_project_detail.Id,
and
Select design_designer(Name)
from design_designer
where design_designer.Id = assign_project_detail.DId
I am trying below code, but it is returning wrong result.
My code:
SELECT
sale_project_detail.*,
design_project_assignment.*,
design_designer.Name
FROM
sale_project_detail,
design_project_assignment,
design_designer
WHERE
NOT EXISTS(SELECT NULL
FROM design_project_assignment
LEFT JOIN design_designer ON design_designer.Id = design_project_assignment.DId
WHERE sale_project_detail.Id = design_project_assignment.SPId)
Thanks in advance.
Try this
SELECT
*
FROM
sale_project_detail as spd
inner join design_project_assignment dpa on dpa.spid <> spd.id
inner join design_designer dd on dd.id = dpa.did;

SQL query Optimization help

I have the the following SQL query
Declare #tempcalctbl Table
(
ItemId varchar(50),
ItemLocation varchar(50),
ItemNo varchar(50),
Width real,
Unit varchar(50),
date datetime
)
Insert Into #tempcalctbl
Select distinct SubId,ItemLocation,ItemNo,
(ABS((Select width From #temptbl a Where ItemProcess ='P1'and a.ItemId = c.ItemId
and a.ItemNo = c.ItemNo and a.ItemLocation = c.ItemLocation)
-(Select width From #temptbl b Where ItemProcess ='P2' and b.ItemId = c.ItemId
and b.ItemNo = c.ItemNo and b.ItemLocation = c.ItemLocation))) * 1000,
Unit,date
From #temptbl c
Group by ItemId,ItemLocation,ItemNo,Unit,date
I was wondering how to optimize this query.
The idea is to find out the different in width (p1's item - p2's item) between ItemProcess 'P1' and 'P2' according to the same ItemID, same ItemNo and same ItemLocation.
I have around 75000 and it took more then 25 minute to get the width differences for all the ItemId.
I tried to use Group by for the width different calculation but it would return multiple row instead of just a value which then would return error. By the way I am use MS SQL server 2008 and #tempcalctbl is a table that I declared in a store procedure.
Does the following help?
INSERT INTO #tempcalctbl
SELECT P1.SubId ,
P1.ItemLocation ,
P1.ItemNo ,
ABS(P1.Width - P2.Width) * 1000 AS Width ,
P1.Unit ,
P1.date
FROM #temptbl AS P1
INNER JOIN #temptbl AS P2 ON P1.ItemId = P2.ItemId
AND P1.ItemNo = P2.ItemNo
AND P1.ItemLocation = P2.ItemLocation
WHERE P1.ItemProcess = 'P1'
AND P2.ItemProcess = 'P2'
EDIT
To make use of indexes, you will need to change your table variable to a temporary table
CREATE TABLE #temptbl
(
ItemId varchar(50),
ItemLocation varchar(50),
ItemNo varchar(50),
Width real,
Unit varchar(50),
date DATETIME,
ItemProcess INT,
SubId INT
)
CREATE NONCLUSTERED INDEX Index01 ON #temptbl
(
ItemProcess ASC,
ItemId ASC,
ItemLocation ASC,
ItemNo ASC
)
INCLUDE ( SubId,Width,Unit,date)
GO
That should speed you up a little.
John Petrak's answer is the best query for this case.
If the speed is still now acceptable, maybe you can store #temptbl at a temporary real table, and create the related index on those four columns.