Skip to main content

SQL Server query store as oracle plan management

Oracle DBA use SQL plan management (SPM) to stabilize query performance, now SQL Server 2016 has similar feature called query store,  This is case study to answer a few questions:

1. Observe how query store work, comparing query plan.

2.Can similar queries which use different literal use other query's plan? if not, what DBA can do to influence optimizer to to choose better query plan compiled for other literal.

3. Can the plan be exported from one sqlserver and import to other sqlserver?

Let's get into it:

1. Observe how query store work, comparing query plans.

I have two queries which are different with literal, one run fast, the other one run slow.

Slow query: use isnull(rh.userid,0) = 255 

SELECT top 1 mh.intnum as intnum,rh.remark as remark,reportid FROM msghead mh inner join msgdetail md on md.intnum = mh.msgintnum left outer join rephistory rh on md.functionnum = 45000 AND md.functionref = rh.intnum WHERE readon < '1900/01/02' AND((isnull(rh.userid,0) = 255 AND md.functionnum = 45000 and rh.remark like 'http%'))

Fast query: use isnull(rh.userid,0) = 167 

SELECT top 1 mh.intnum as intnum,rh.remark as remark,reportid FROM msghead mh inner join msgdetail md on md.intnum = mh.msgintnum left outer join rephistory rh on md.functionnum = 45000 AND md.functionref = rh.intnum WHERE readon < '1900/01/02' AND((isnull(rh.userid,0) = 167 AND md.functionnum = 45000 and rh.remark like 'http%'))

I ran the two queries a few times, notice the two query plans are different, even the slow query generated a good plan at one time, I guess I am lucky.

There is a way to guide SQL Server optimizer to choose good plan, I have a case study documented here:

https://walkthrough-dba.blogspot.com/2021/10/case-study-of-sql-server-plan-guide.html

I use the following query to find out query plan history, Let's call this dba_query_store_1:

SELECT qsp.query_id, QSP.plan_id,  QST.query_sql_text, qsq.query_hash, qsp.query_plan_hash, QSRS.last_duration,

QSRS.avg_duration, qsp.query_plan, QSQ.last_execution_time,  -- timezone is not right, show 7 hours ahead, also sometimes it's even less than the first_execution_time

QSRS.first_execution_time,  -- timezone is not right, show 7 hours ahead

QSRS.avg_logical_io_reads,QSRS.avg_logical_io_writes 

FROM sys.query_store_plan AS QSP  JOIN sys.query_store_query AS QSQ      ON QSP.query_id = QSQ.query_id  

JOIN sys.query_store_query_text AS QST      ON QSQ.query_text_id = QST.query_text_id 

JOIN sys.query_store_runtime_stats  QSRS   ON QSP.plan_id =QSRS.plan_id

where QST.query_sql_text like 'SELECT top 1 %'

order by QSQ.last_execution_time 


(query_id=30 and plan_id=4) is the slow one, (plan_id=6) is faster one

You can save the query_plan as .sqlplan and compare it to other plan, I will do that later.

So, let me fix the query to use a good and bad plan respectively

EXEC sp_query_store_force_plan @query_id = 30, @plan_id = 4;

Run the slow query, it completed slow as expected, and dba_query_store_1 and observe which plan did it run, it generated a new plan plan_id=13, compare plan_id= 13 and plan_id=4, they are same as operators and steps, though the node id is different but in right order


Now switch it to plan_id=6, and run the query in SSMS with 'include actual execution plan', it complete d fast as expected.

EXEC sp_query_store_force_plan @query_id = 30, @plan_id = 6;

This time it use plan_id=6 and did not create new plan_id. interesting.

That's all for the observation. now let's move to next question:

2.  Can similar queries which use different literal use other query's plan? if not, what DBA can do to influence optimizer to to choose better query plan compiled for other literal.

Let's fix the slow query with the fast query's plan:

EXEC sp_query_store_force_plan @query_id = 30, @plan_id = 5;

Msg 12406, Level 11, State 1, Procedure sp_query_store_force_plan, Line 1 [Batch Start Line 83]

Query plan with provided plan_id (5) is not found in the Query Store for query (30). Check the plan_id value and rerun the command.

So the query plan is not exchangeable to the queries that use different literal. 

Can DBA give optimizer some hint as Oracle can do with outline? the answer is yes, plan guide can do it, I documented the case study here:

https://walkthrough-dba.blogspot.com/2021/10/case-study-of-sql-server-plan-guide.html

After I have a good plan for the slow query, then I can force the plan for the slow query, just as shown above.

I can also use another way of query guide: 

select statement blabla Option (use plan N'xml plan of faster query literal here')

which is documented in 

https://walkthrough-dba.blogspot.com/2021/10/case-study-of-sql-server-plan-guide.html

Let's move to question 3:

3. Can the plan be exported from one sqlserver and import to other sqlserver?

This link suggest that I can do it, let's give it a try.

https://dba.stackexchange.com/questions/231650/how-can-i-export-query-store-data

sp_configure 'remote admin connections',1

reconfigure

C:\>sqlcmd -S sqlservername -E -A

1> use dbname

2> go

1> select * into dropit from sys.query_store_plan

2> go

(13 rows affected)

1> delete from dropit where plan_id<>5

2> go

(12 rows affected)

1> update dropit set query_id=30, plan_id=14

2> go

(1 rows affected)

1> insert into sys.query_store_plan select * from dropit

2> go

Msg 259, Level 16, State 1, Server , Line 1

Ad hoc updates to system catalogs are not allowed.

ok, let's try another way:

1> select * into dropit from dbname.sys.plan_persist_plan where plan_id=5

2> go

1> update dropit set query_id=30, plan_id=15

2> go

1> INSERT INTO  dbname.sys.plan_persist_plan SELECT * FROM dropit
2> go

(1 rows affected)
1> EXEC sp_query_store_force_plan @query_id = 30, @plan_id = 15;
2> go
Msg 12406, Level 11, State 1, Server , Procedure sp_query_store_force_plan, Line 1
Query plan with provided plan_id (15) is not found in the Query Store for query (30). Check the plan_id value and rerun the command.
1> delete from eatecx.sys.plan_persist_plan where plan_id=15
2> go

(1 rows affected)
1>

So I cannot steal and force plan from another query literal, I do think that I can trick it more and make it work, but because I already have solution of guide the slow query to use a good plan by using option (use plan N'xml faster plan'), why bother to trick it this way? I can just guide the slow query to use faster plan, then force it as shown above.

That's all. feel better to know that Microsoft SQL Server is having some of Oracle's SPM and outline features!

Comments

Popular posts from this blog

Opatch apply/lsinventory error: oneoff is corrupted or does not exist

I am applying the quarterly patch for 19c RDBMS, I tried using napply but failed, but somehow it corrupted the inventory though nothing applied. further apply and lsinventory command ran into error like this: $ ./OPatch/opatch lsinventory Oracle Interim Patch Installer version 12.2.0.1.21 Copyright (c) 2020, Oracle Corporation.  All rights reserved. Oracle Home       : /u02/app/oracle/19.0.0 Central Inventory : /u01/app/oraInventory    from           : /u02/app/oracle/19.0.0/oraInst.loc OPatch version    : 12.2.0.1.21 OUI version       : 12.2.0.7.0 Log file location : /u02/app/oracle/19.0.0/cfgtoollogs/opatch/opatch2020-09-08_13-35-59PM_1.log Lsinventory Output file location : /u02/app/oracle/19.0.0/cfgtoollogs/opatch/lsinv/lsinventory2020-09-08_13-35-59PM.txt -------------------------------------------------------------------------------- Inventory load failed... OPatch cannot load inventory ...

oracle dba_hist_sysmetric_summary

found this blog is helpful to get CPU and IO statistics on oracle database. http://shob-dbadmin.blogspot.ca/2012/12/how-to-find-total-io-of-database.html courtesy to  Shomil Bansal , below are hist writing, not mine. How to find total IO of the database instance Total IO of database instance is sum of the physical reads, physical writes and redo writes. There are several views to find these values. v$sysmetric  - Reports metric values for only the most current time sample 60 secs. v$sysmetric_summary  - Reports metric values for time sample of 1 hour. v$sysmetric_history  - Reports metric values every 60 sec from the time instance is up. Better way to analyse IO using this view to take deltas between two time periods. dba_hist_sysmetric_history  - All the above views are refreshed when the instance is restarted. This view, part of AWR, stores the historical stats. I have used this view for my report. Query: ====== set lines 350...

ORA_RMAN_SGA_TARGET

assume that we lost all the files of oracle database but we do have rman backup, when trying to bring up a dummy database before restore start, I get this error. RMAN> startup nomount force; WARNING: cannot translate ORA_RMAN_SGA_TARGET value startup failed: ORA-01078: failure in processing system parameters ORA-01565: error in identifying file '+DATA/PROD/spfilePROD.ora' ORA-17503: ksfdopn:2 Failed to open file +DATA/PROD/spfilePROD.ora ORA-15056: additional error message ORA-17503: ksfdopn:DGOpenFile05 Failed to open file +DATA/prod/spfileprod.ora ORA-17503: ksfdopn:2 Failed to open file +DATA/prod/spfileprod.ora ORA-15173: entry 'spfileprod.ora' does not exist in directory 'prod' ORA-06512: at line 4 starting Oracle instance without parameter file for retrival of spfile RMAN-00571: =========================================================== RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS =============== RMAN-00571: =================================...