SQL - Better Performance vith a View - sql

I'm running on SQL Server 2014, and have a Customer table related to a table with orders. The Order table has e.g 500.000 rows - 100.000 for each of 5 customers. So when looking for all orders for a specific date for a specific customer, the SQL would be
Select *
from Orders
Where idCustomer = 1
and OrderDate = '20160225'
This query should look through 500.000 records to find relevant orders.
Would it be better for performance to create 5 views, a view for each customer and then querying the view:
Select *
from View_Orders_Customer1
Where OrderDate = '20160225'
Or do I have to create 5 tables Order_Customer1, Order_Customer2 etc. - instead ??

I don't recommend create view for each customer .. but you can add Index in your table http://www.w3schools.com/sql/sql_create_index.asp
Also you can add Index on your view to enhance your select performance
https://technet.microsoft.com/en-us/library/ms187864(v=sql.105).aspx
I have table contains more than 700,000 records and applying indexing in table and view helped me very much

For same data model, use same table(s). More than one table or view is not good design,
You should look at execution plan, and create necessary indexes,
After performance tuning with table indexes, you can use Indexed Views,
https://msdn.microsoft.com/en-us/library/ms191432(v=sql.120).aspx

Related

Extract data from view ORACLE performance

Hello I created a view to make a subquery ( select from two tables)
this the sql order :
CREATE OR REPLACE VIEW EMPLOYEER_VIEW
AS
SELECT A.ID,A.FIRST_NAME||' '||A.LAST_NAME AS NAME,B.COMPANY_NAME
FROM EMPLOY A, COMPANY B
WHERE A.COMPANY_ID=B.COMPANY_ID
AND A.DEPARTEMENT !='DEP_004'
ORDER BY A.ID;
If I select data from EMPLOYEER_VIEW the average execution time is 135,953 s
Table EMPLOY contiens 124600329 rows
Table COMPANY contiens 609 rows.
My question is :
How can i make the execution faster ?
I created two indexes:
emply_index (ID,COMPANY_ID,DEPARTEMENT)
and company_index(COMPANY_ID)
Can you help me to make selections run faster ? ( creating another index or change join )
PS: I Can't create a materialized view in this database.
In advance thanks for help.
You have a lot of things to do.
If you must work with a view, and can not create a scheduled job to insert data in a table, I will remove my answer.
VIEWs does not have the scope to support hundred of million data. Is for few million.
INDEXes Must be cleaned when data are inserting. If you insert data with an index the process is 100 times slower. (You can drop and create or update them).
In table company CREATE PARTITION.
If you have a lot of IDs, use RANGE.
If you have around 100 IDs LIST PARTITION.
You do not need Index, because the clause to JOIN does not optimize, INDEXes is specified to strict WHERE Clause.
We had a project with 433.000.000 data, and the only way to works was playing with partitions.

SQL - Query Performance Slow When Joining Two Views with Where Clause

I am running the following query in SQL Server which gives me a result in just 5 seconds with 80,000+ rows and 75+ columns:
SELECT * FROM VIEW_ITEM_STOCK_LEDGER AS ItemLedger
LEFT JOIN VIEW_PRODUCT_WITH_CHARACTERISTIC_COLUMN_DATA AS Characteristics
ON Characteristics.Code = ItemLedger.ItemCode
But when I add a WHERE clause to the query it takes too long time to execute the query. It takes more than 5 minutes for 13450 records.
SELECT * FROM VIEW_ITEM_STOCK_LEDGER AS ItemLedger
LEFT JOIN VIEW_PRODUCT_WITH_CHARACTERISTIC_COLUMN_DATA AS Characteristics
ON Characteristics.Code = ItemLedger.ItemCode
WHERE (ItemLedger.VoucherTypeCode=204 OR ItemLedger.VoucherTypeCode=205)
What could be the reason? How do I solve this?
It sounds to me like there is no index on the column VoucherTypeCode.
If VoucherTypeCode is a column of a table in your database, you can try indexing that column (see this article about creating indexes on MS Docs)
If VoucherTypeCode is a product of multiple columns, you can try indexing the view itself (see this Article about indexed views on sqlshack.com)
Alternatively, if you can't/don't want to create an index, check out the accepted answer in this StackOverflow-Thread

Unindexed views v/s Queries

I'm creating a view which contains subquery as specified witht he following SQL query on SQL Server 2012.
CREATE VIEW [dbo].[VIEW_Detail] WITH SCHEMABINDING
AS
SELECT a.ID, a.Name1, a.Name2,
STUFF
((SELECT CAST(',' AS varchar(max)) + t .Name1
FROM dbo.Synonyms AS s
INNER JOIN dbo.Details AS t ON s.SynonymTSN = t .TSN
WHERE s.oID= a.ID FOR XML PATH('')), 1, 1, '') AS Synonym
FROM a.Details
WHERE (a.Rank <= 100)
Since the definition contains a subquery I'm not able to create an Indexed view. Will it be faster to use a query instead of the view to retrieve data if my tables are indexed.Or will an unindexed view will still perform better than using a query. The view currently contains more than 50,000 rows. What other query optimizations can I use?
PS: I don't care about performance on insert/update
A view is simply a single SELECT statement saved using a name (i.e View Name), There is no performance benefit using view over an ad-hoc query.
Yes Indexed views can increase the performance but they come with a longgggggggg list of limitations. As they are materialized and Also other queries which are not calling this indexed view but can benefit from indexes defined on this view will make use of these indexes.
In your case you have a sub-query and also using FOR XML clause, they both are not allowed inside an indexed view.
To optimize you query you need to look at the execution plan first and see if query is doing table or Clustered Index scans. Try adding some indexes and try to get a seek instead of a scan.
Looking at this query I think if you have Indexes on TSN, ID and RANK columns of dbo.Details table and SynonymTSN column of dbo.Synonyms table, it can improve the performance of this query.
On a side note 50,000 rows isn't really a big number of rows as long as you have primary keys defined on these two tables, you should get a reasonable performance with is pretty simple query.

SQL Server 2000 Indexed View with Max Subquery

I have a contracts table that is large and that we have many stored procedures that query for contracts with a status of Open. Less than 10% of the contracts are open and this number is shrinking as the DB grows. I thought I could create an Indexed view of the open contracts in order to speed up some of our queries. The problem is that the status is not on the contract table and I need a subquery to retrieve the data I want. (SQL Server then does a clustered index scan on the whole table in the queries I have looked at)
Here is the condensed version of the view (I removed the 30 other columns from the contract table)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[vw_OpenContractsIndexed]
WITH SCHEMABINDING
AS
SELECT c.ContractID
FROM dbo.NMPT_Contract AS c INNER JOIN
dbo.NMPT_ContractStatus AS cs ON c.ContractID = cs.ContractID AND cs.ContractStatusCreated =
(SELECT MAX(ContractStatusCreated) AS Expr1
FROM dbo.NMPT_ContractStatus AS cs2
WHERE (ContractID = c.ContractID)) INNER JOIN
dbo.CMSS_Status AS s ON cs.StatusID = s.StatusID
WHERE (s.StatusCode = 'OPN')
If I try to create an index on the view (unique clustered on contractid) I get the following
Creation Failed for Index
It contains one or more disallowed constructs. (Microsoft SQL Server, Error 1936)
From what I can gather it is the Max in the subquery that is the problem??
Other than putting the status on the contracts table (where I personally think it belongs) are there any suggestions for optimising this situation. Failing that will other versions of SQL Server allow this indexed view?
From TechNet regarding Indexed Views in SS 2000:
There are several restrictions on the syntax of the view definition.
The view definition must not contain the following:
COUNT(*)
ROWSET function
Derived table
self-join
DISTINCT
STDEV, VARIANCE, AVG
Float*, text, ntext, image columns
Subquery
full-text predicates (CONTAIN, FREETEXT)
SUM on nullable expression
MIN, MAX
TOP
OUTER join
UNION
You're using MAX, and a subquery, both of which are not allowed.
To get advice on how to get around this, you need to share some data and what you are trying to do.
It is not a "View" solution and will require more work to accomplish, but you can create denormalized table which will hold the result of the view. This way, all reads for Open contracts can go against that table. This will be the fastest, but will require maintenance of the new table.
Creating an indexed view is quiet difficuylt task as it has so many restirction and one is related to self join as well. You have self join here.No other views etc.
Other thing for these kind of master tables if you are using just a single status like 'OPEN' in you case I would suggest that instead of joining the table (master table with status code) just declare statusid variable and then store the value for status OPEN there and then use that value in final query. This will avoid extra join with a master table.
I would suggest that you store the data for open status in temp table before joining with contract table in final statement. You can have an index on statusid,customerid and contractcreationdate. Then force this index to get the contractId into a temp table like
select contractid into #temp from NMPT_ContractStatus
where statusid =#statusid group by contractid
having datefield = max(datefield)
Now join this temp table with the Contract table.
But before creating any kind of indexes make sure that the overhead of these are much less than the benefits you are getting.

Query only the required mview from the union

I have materialized view manually partitioned by month
create materialized view MV_MVNAME_201001 as
select MONTH_ID, AMOUNT, NAME
from TABLE_NAME_201001
201002, 201003, ..., 201112, 2012, 2009
Now i need query from these views, take only the required views.
Is it possible, without involving the client side?
example query
select AMOUNT, NAME
from (
--union all mview
)
where month_id >= 201003
and month_id < 201101
should look only to the MV_MVNAME_201003 .. MV_MVNAME_201012
The materialized view is "materialized". It is a phisical table with data within it.
The query that produce the materialized view is used only when you refresh data, not on querys.
Oracle doesn't know where data came from(in your case - a union from several distinct tables), unless you specify it somehow, for example - a column.
But in your specific case you have the column month_id, on witch you can partition the table.
When you specify the month or range of months, it will scan only the correspondent partitions.
UDPATE:
Now I understand better your question, but I cannot give you a better answer. Your question has nothing to do with mviews. Mviews can be tables. Your problem is the same. You want to select only from some tables, dynamic. For this was created partitioning. Probably old dogs know a trick...