I have a fairly basic query such as below that I am needing to execute very often and as fast as possible:
Select
B.ID, B.FirstName, B.LastName
From
TableA as A
Join
TableB as B on A.ID = B.ID
Where
A.OtherID = #Input
So my thought was to create a stored procedure with parameters of #Input. I figure that since the execution plan was saved on the server side this would increase the speed.
I however want to increase it further and thought that maybe an Index might help. But I have not dealt with indexes much just read a little.
What all information would you need to help me build an index that can help?
Would an Index help?
Also this stored procedure is going to be called from Excel 2013 if that makes a difference on something else we can do to speed it up.
We are using SQL Server 2012.
SQL Server Management Studio is remarkably good at recommending indexes. Run your query and see what it says.
Without knowing more about your schema or the OLAP patterns, I can only make a suggestion...
Is "ID" the key field in TableA and/or TableB? If so, they're already indexed.
I'd say you're looking at two indexes:
An index on TableA for OtherID that includes ID. This will help SQL find values of OtherID and return the ID's associated with them.
An index on TableB on ID that includes FirstName and LastName. This will help SQL with the join and save a trip back to the rows for FirstName and LastName.
Related
Please forgive me if I open a new thread about looping in PL/SQL but after reading dozens of existing ones I'm still not able to perform what I'd like to.
I need to run a complex query on a view of a table and the only way to shorten running time is to filter through a where clause based on a variable to which such table is indexed (otherwise the system ends up doing a full scan of the table which runs endlessly)
The variable the table is indexed on is store_id (string)
I can retrieve all the store_id I want to query from a separate table:
e.g select distinct store_id from store_anagraphy
Then I'd like to make a loop that iterate queries with the store_id identified above
e.g select *complex query from view_of_sales where store_id = 'xxxxxx'
and append (union) all the result returned by each of this queries
Thank you very much in advance.
Gianluca
In theory, you could write a pipelined table function that ran multiple queries in a loop and made a series of pipe row calls to return the results. That would be pretty unusual but it could be done.
It would be far, far more common, however, to simply combine the two queries and run a single query that returns all the rows you want
select something
from your_view
where store_id in (select distinct store_id
from store_anagraphy)
If you are saying that you have tried this query and Oracle is choosing to do a table scan rather than using the index then what you really have is a tuning problem. Most likely, statistics on one or more objects are inaccurate which leads Oracle to expect that this query would return more rows than it really will thus favoring the table scan. You should be able to fix that by fixing the statistics on the objects. In a pinch, you could also use hints to force an index to be used.
i'm struggling to understand what the TABLE clause does, per oracle docs:
it transforms a collection like a nested table into a table which could be used in an sql statement.
which seems clear enough but i don't know how it works in practice.
these are the relevant types and tables;
create type movies_type as Table of ref movie_type;
create type actor_type under person_type
(
starring movies_type
) Final;
create table actor of actor_type
NESTED TABLE starring STORE AS starring_nt;
i want to list actors and movies they starred in, this works
select firstname, lastname, value(b).title
from actor2 a, table(a.starring) b;
but i don't understand why. why isn't this
actor2 a, table(a.starring) b
a Cartesian product?
also, why does value(b) work here?, since it's table of refs, it should be deref, but that doesn't work.
my question is:
why does this query work as intended? i would expect it to list every actor with every movie (Cartesian product) as there are no specified conditions on how to join, and why does value(b) work here?, since it's table of refs, it should be deref, but that doesn't work.
i don't have a mental model for oracle sql, help is very much appreciated on how to learn properly.
thank you very much.
It’s not a Cartesian product because table(a.starring) is correlated by a: For each row in a it is running the table function against its starring nested table.
This is not a very common way of data modelling in Oracle, usually you would use a junction table to allow for a properly normalised model (which usually is much easier to query and allows for better for performance)
I have over million records in these tables in both the databases.
I am trying to figure out data in both the tables acros databases.
SELECT COUNT(*) FROM DB1.MYTABLE WHERE SEQ_NO NOT IN(SELECT SEQ_NO FROM DB2.MYTABLE) AND FILENAME NOT LIKE '%{%'
and PT_TYPE NOT IN(15,24,268,284,285,286,12,17,9,290,214,73) AND STTS=1
The query is taking ages. Is there any way I can make it fast?
Appreciate your help in advance
Do you actually mean different databases? Or do you mean different schemas? You talk about different databases but the syntax appears to be using tables in two different schemas, not two different databases. I don't see any references to a database link which would be needed if there were two different databases but perhaps DB2.MYTABLE is supposed to be a synonym for MYTABLE#DB2.
It would be helpful if you could post the query plan that is generated. It would also be useful to indicate what indexes exist and how selective each of these predicates is. My guess is that modifying the query to be
SELECT count(*)
FROM schema1.mytable a
WHERE NOT EXISTS (
SELECT 1
FROM schema2.mytable b
WHERE a.seq_no = b.seq_no )
AND a.filename NOT LIKE '%{%'
AND a.pt_type NOT IN (15,24,268,284,285,286,12,17,9,290,214,73)
AND a.stts = 1
might be more efficient if most of the rows in SCHEMA1.MYTABLE are eliminated because the SEQ_NO exists in SCHEMA2.MYTABLE.
Let's say I have a Big and a Bigger table.
I need to cycle through the Big table, that is indexed but not sequential (since it is a filter of a sequentially indexed Bigger table).
For this example, let's say I needed to cycle through about 20000 rows.
Should I do 20000 of these
set #currentID = (select min(ID) from myData where ID > #currentID)
or
Creating a (big) temporary sequentially indexed table (copy of the Big table) and do 20000 of
#Row = #Row + 1
?
I imagine that doing 20000 filters of the Bigger table just to fetch the next ID is heavy, but so must be filling a big (Big sized) temporary table just to add a dummy identity column.
Is the solution somewhere else?
For example, if I could loop through the results of the select statement (the filter of the Bigger table that originates "table" (actually a resultset) Big) without needing to create temporary tables, it would be ideal, but I seem to be unable to add something like an IDENTITY(1,1) dummy column to the results.
Thanks!
You may want to consider finding out how to do your work set based instead of RBAR. With that said, for very big tables, you may want to not make a temp table so that you are sure that you have live data if you suspect that the proc may run for a while in production. If your proc fails, you'll be able to pick up where you left off. If you use a temp table then if your proc crashes, then you could lose data that hasn't been completed yet.
You need to provide more information on what your end result is, It is only very rarely necessary to do row-by-row processing (and almost always the worst possible choice from a performance perspective). This article will get you started on how to do many tasks in a set-based manner:
http://wiki.lessthandot.com/index.php/Cursors_and_How_to_Avoid_Them
If you just want a temp table with an identity, here are two methods:
create table #temp ( test varchar (10) , id int identity)
insert #temp (test)
select test from mytable
select test, identity(int) as id into #temp from mytable
I think a join will serve your purposes better.
SELECT BIG.*, BIGGER.*, -- Add additional calcs here involving BIG and BIGGER.
FROM TableBig BIG (NOLOCK)
JOIN TableBigger BIGGER (NOLOCK)
ON BIG.ID = BIGGER.ID
This will limit the set you are working with to. But again it comes down to the specifics of your solution.
Remember too, you can do bulk inserts and bulk updates in this manner too.
I'm using LinqToSql to query a small, simple SQL Server CE database.
I've noticed that any operations involving sub-properties are disappointingly slow.
For example, if I have a Customer table that is referenced by an Order table, LinqToSql will automatically create an EntitySet<Order> property. This is a nice convenience, allowing me to do things like Customer.Order.Where(o => o.ProductName = "Stopwatch"), but for some reason, SQL Server CE hangs up pretty bad when I try to do stuff like this. One of my queries, which isn't really that complicated takes 3-4 seconds to complete.
I can get the speed up to acceptable, even fast, if I just grab the two tables individually and convert them to List<Customer> and List<Order>, then join then manually with my own query, but this requires a lot of extra code. LinqToSql generates these EntitySet<T> properties automatically--I'd like to use them.
So, how can I improve the performance? For example, are there any DataContext options that would help?
Note: My database in its initial state is only about 250K and I don't expect it to grow to more than 1-2Mb. So, it's not like there are a lot of records.
Update
Here are the table definitions for the example I used in my question:
create table Order
(
Id int identity(1, 1) primary key,
ProductName ntext null,
Quantity int null
)
create table Customer
(
Id int identity(1, 1) primary key,
OrderId int null references Order (Id)
)
I've not used SQL Server CE with Linq to SQL before, but with such a small DB, my gut tells me the performance issue has more to do with poor query optimization than disk access.
Try getting the SQL query from your Linq to SQL objects to see what might be happening. Perhaps run those queries manually against the CE database to see how they perform.
It's very possible that just adding the correct indexes will solve the problem.
You might also try LinqToSQL Profiler. http://l2sprof.com/