HiveBrain v1.2.0
Get Started
← Back to all entries
snippetsqlMinor

How to improve the execution plan to speed up the query

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
thequeryimproveplanhowspeedexecution

Problem

I am trying to improve the execution plan to speed up the query. Currently the query won't finish after nine hours. Right now I am getting a lot of hash match and merge join. I have very limited knowledge of execution plans but from what I think I know the hash match is very slow and the merge join is not much better. Although I am not exactly sure what I am hoping to find as this part of the SQL is still really new to me.

Each table used except for ZZ_PropertyTable has a Primary key on Casino_ID, CasinoCode, Gamingdate, PlayerID in that order. Along with a unique nonclustered index which is the same columns in the same order but with an include clause to cover the this query. The ZZ_PropertyTable has a Primary key on Casino_ID, CasinoCode.

I did not think it mattered but just to be sure I put all the joins in the same order as the primary keys.

I am not sure if maybe I should write the code differently or if i need different indexes. Any help you can provide even if it just a link to something I can read to better understand this would be greatly appreciated.

I am using SQL Server 2012 below is the code as well as a link to the execution plan:

https://www.brentozar.com/pastetheplan/?id=rymXZWnHb

```
Select
PL.Casino_ID
,PL.CasinoCode
,PT.PropertyName
,PL.PlayerID
,PL.Gamingdate
,1 as TotalTrips
,isnull(TS.SlotTrips,0) as SlotTrips
,isnull(TT.TableTrips,0) as TableTrips
,isnull(GT.GamingTrips,0) as GamingTrips
,Isnull(TS.SlotCoinIn,0) as SlotCoinIn
,isnull(TT.TableDrop,0) as TableDrop
,isnull(TS.SlotTheoWin,0) as SlotTheoWin
,isnull(TT.TableTheoWin,0) as TableTheoWin
,isnull(TS.SlotActualWin,0) as SlotActualWin
,isnull(TT.TableActualWin,0) as TableActualWin
,isnull(TS.SlotTheoWin
+ TT.TableTheoWin,0) as TotalTheo
,isnull(TS.SlotActualWin
+ TT.TableActualWin,0) as T

Solution

First let's start where the problem likely isn't to be. Cardinality estimates look fine. You aren't doing any filtering and all of the joins are left joins on the primary keys of the tables. Table access methods look fine. You've defined the best possible indexes for the tables and SQL Server is doing index scans on those tables. Seems perfectly reasonable because you need all of the rows from the tables. Join order seems ok. None of the tables will decrease or increase the size of the result set (if ZZ_PlayerIDList is the starting table). A poor join order could lead to some unnecessary repartitioning but I don't see that here.

That means the join type. There are four parallel merge joins and the rest are parallel hash joins. There are some edge cases with parallel merge join that perform very poorly. I'm not a fan of it for this type of query in which you data is already sorted. The parallel aspect of it means you read the sorted data in parallel (which breaks the sorting) only to have to sort it again. There's a lot of repartitioning rows and sorting which would be avoided with MAXDOP 1 merge joins. There are also hints in the query plan that this query isn't getting as much memory as it wants.

I would try adding a MAXDOP 1 hint to the query and making changes so that you get all merge joins. For testing purposes it may be helpful to add OPTION (MERGE JOIN) as a hint. I would not expect that query to take more than 9 hours. If it does that sounds like some kind of hardware, configuration, or blocking issue.

From a data model point of view, you could improve performance of the query by combining together some of your tables. All of them have the same primary keys. For example, UX_ZZGamingTrips has 18260100 rows and UX_ZZTrackedSlot has 18259900 rows. Would combing those tables into one table really be a bad thing? What do you gain by separating them?

Context

StackExchange Database Administrators Q#180175, answer score: 2

Revisions (0)

No revisions yet.