Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2005-07-29 : 11:17:23
|
--I have a query. It currently takes 42 seconds. I need it to take 5 or less.--1) DDLCREATE TABLE [Companies] ([COM_CompanyID] uniqueidentifier NOT NULL, [COM_Name] varchar (50) NOT NULL)CREATE TABLE [CompanyDepartments] ([DEP_DepartmentID] uniqueidentifier NOT NULL, [DEP_CompanyID] uniqueidentifier NOT NULL, [DEP_DepName] varchar (50) NOT NULL)CREATE TABLE [CompanyContacts] ([CON_ContactID] uniqueidentifier NOT NULL, [CON_DepartmentID] uniqueidentifier NOT NULL, [CON_PersonID] uniqueidentifier NOT NULL,[CON_Type] tinyint NOT NULL)CREATE TABLE [People] ([PEO_PersonID] uniqueidentifier NOT NULL,[PEO_Name] varchar (50) NOT NULL)CREATE TABLE [Products] ([PRO_ProductID] uniqueidentifier NOT NULL, [PRO_OwnerID] uniqueidentifier NOT NULL, [PRO_BaseProductID] uniqueidentifier NOT NULL)CREATE TABLE [BaseProducts] ([BAS_ProductID] uniqueidentifier NOT NULL)ALTER TABLE dbo.Companies ADD CONSTRAINT DF_Companies_COM_CompanyID DEFAULT (newid()) FOR COM_CompanyIDGOALTER TABLE dbo.Companies ADD CONSTRAINT DF_Companies_COM_Name DEFAULT ('') FOR COM_NameGOCREATE CLUSTERED INDEX IX_CompaniesName ON dbo.Companies ( COM_Name ) ON [PRIMARY]GOALTER TABLE dbo.Companies ADD CONSTRAINT PK_Companies PRIMARY KEY NONCLUSTERED ( COM_CompanyID ) ON [PRIMARY]GOALTER TABLE dbo.CompanyDepartments ADD CONSTRAINT DF_CompanyDepartments_DEP_DepartmentID DEFAULT (newid()) FOR DEP_DepartmentIDGOALTER TABLE dbo.CompanyDepartments ADD CONSTRAINT DF_CompanyDepartments_DEP_DepName DEFAULT ('') FOR DEP_DepNameGOCREATE CLUSTERED INDEX IX_CompanyDepartmentsCompanyID ON dbo.CompanyDepartments ( DEP_CompanyID ) ON [PRIMARY]GOALTER TABLE dbo.CompanyDepartments ADD CONSTRAINT PK_CompanyDepartments PRIMARY KEY NONCLUSTERED ( DEP_DepartmentID ) ON [PRIMARY]GOALTER TABLE dbo.CompanyContacts ADD CONSTRAINT DF_CompanyContacts_CON_ContactID DEFAULT (newid()) FOR CON_ContactIDGOALTER TABLE dbo.CompanyContacts ADD CONSTRAINT DF_CompanyContacts_CON_ContactTypeEnum DEFAULT (254) FOR CON_TypeGOCREATE CLUSTERED INDEX IX_CompanyContactsPersonID ON dbo.CompanyContacts ( CON_PersonID ) ON [PRIMARY]GOALTER TABLE dbo.CompanyContacts ADD CONSTRAINT PK_CompanyContacts PRIMARY KEY NONCLUSTERED ( CON_ContactID ) ON [PRIMARY]GOALTER TABLE dbo.People ADD CONSTRAINT DF_People_PEO_PersonID DEFAULT (newid()) FOR PEO_PersonIDGOALTER TABLE dbo.People ADD CONSTRAINT DF_People_PEO_Name DEFAULT ('') FOR PEO_NameGOCREATE CLUSTERED INDEX IX_PeopleName ON dbo.People ( PEO_Name ) WITH FILLFACTOR = 80 ON [PRIMARY]GOALTER TABLE dbo.People ADD CONSTRAINT PK_People PRIMARY KEY NONCLUSTERED ( PEO_PersonID ) ON [PRIMARY]GOALTER TABLE dbo.Products ADD CONSTRAINT DF_Products_PRO_ProductID DEFAULT (newid()) FOR PRO_ProductIDGOCREATE CLUSTERED INDEX IX_ProductsBaseProductID ON dbo.Products ( PRO_BaseProductID ) ON [PRIMARY]GOALTER TABLE dbo.Products ADD CONSTRAINT PK_Products PRIMARY KEY NONCLUSTERED ( PRO_ProductID ) ON [PRIMARY]GO--2) Sample Data DMLINSERT INTO Companies (COM_Name) VALUES ('MyCompany')INSERT INTO CompanyDepartments (DEP_DepName, DEP_CompanyID) SELECT 'MyDep', (SELECT COM_CompanyID FROM Companies)INSERT INTO People (PEO_Name) VALUES ('MyPerson')INSERT INTO CompanyContacts (CON_DepartmentID, CON_PersonID)SELECT (SELECT DEP_DepartmentID FROM CompanyDepartments), (SELECT PEO_PersonID FROM People)INSERT INTO BaseProducts (BAS_ProductID) VALUES (NEWID())INSERT INTO Products (PRO_OwnerID, PRO_BaseProductID) SELECT (SELECT CON_ContactID FROM CompanyContacts), (SELECT BAS_ProductID FROM BaseProducts)INSERT INTO Products (PRO_OwnerID, PRO_BaseProductID) SELECT (SELECT TOP 1 COM_CompanyID FROM Companies), (SELECT TOP 1 BAS_ProductID FROM BaseProducts)/*In the live DB, these are the real record counts:Companies 62KCompanyDepartments 104KPeople 590KCompanyContacts 285KBaseProducts 600KProducts 300K*/--3) Attempt DML --populate test parameterDECLARE @CompanyID UNIQUEIDENTIFIERSET @CompanyID = (SELECT COM_CompanyID FROM Companies)SELECT PRO_ProductID, BAS_ProductID FROM CompanyDepartments INNER JOIN CompanyContacts ON CompanyDepartments.DEP_DepartmentID = CompanyContacts.CON_DepartmentID INNER JOIN Products ON CompanyContacts.CON_ContactID = Products.PRO_OwnerIDINNER JOIN BaseProducts ON Products.PRO_BaseProductID = BaseProducts .BAS_ProductIDWHERE (DEP_CompanyID = @CompanyID) UNIONSELECT PRO_ProductID, BAS_ProductIDFROM Companies INNER JOIN Products ON Companies.COM_CompanyID = Products.PRO_OwnerIDINNER JOIN BaseProducts ON Products.PRO_BaseProductID = BaseProducts .BAS_ProductIDWHERE (COM_CompanyID = @CompanyID)--4)/*Basically Companies or Contacts can be the owners of Products. Sometimes I want to bring back all the Products that a company owns - including that of all it's contacts.This DML attempt runs quick, but I don't think it scales up to the amount of records I mention above.*/ |
|
Kristen
Test
22859 Posts |
Posted - 2005-07-29 : 15:19:51
|
Might benefit from indexes onCON_DepartmentIDPRO_OwnerIDBAS_ProductIDso that all sides of the JOINS are indexes.I've never believed in this, but its what the books say!Do you need a UNION or could you use a UNION ALL - that would save some CPU cyclesKristen |
|
|
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2005-08-01 : 03:29:51
|
I tried indexes on CON_DepartmentID and BAS_ProductID and it actually slowed it down - probably because the optimizer had to choose between indexes, not sure.More than 99% of the records have PRO_OwnerID as the same value. So I'm going to try a partition on the Products table and put that PRO_OwnerID in as a constraint on one of the two tables and then use a view. We'll see if that fixes it. |
|
|
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2005-08-01 : 06:01:06
|
That worked :-)If you pass an invalid ID in for @CompanyID, would that result in the query running considerably slower because of joining on nulls or something? |
|
|
|
|
|
|
|