sch_aus.sql 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617
  1. {**************************************************************************}
  2. {* *}
  3. {* Licensed Materials - Property of IBM and/or HCL *}
  4. {* *}
  5. {* IBM Informix Dynamic Server *}
  6. {* (c) Copyright IBM Corporation 2001, 2016. All rights reserved. *}
  7. {* (c) Copyright HCL Technologies Ltd. 2017. All Rights Reserved. *}
  8. {* *}
  9. {**************************************************************************}
  10. DATABASE sysadmin;
  11. {*********************************************************
  12. *
  13. * The following section load all the parameters
  14. * utilized by AUS
  15. *
  16. ********************************************************
  17. *}
  18. INSERT INTO ph_threshold
  19. (id,name,task_name,value,value_type,description)
  20. VALUES
  21. (0,"AUS_AGE","Auto Update Statistics Evaluation","30","NUMERIC(6.2)",
  22. "The statistics are rebuilt after this many days.");
  23. INSERT INTO ph_threshold
  24. (id,name,task_name,value,value_type,description)
  25. VALUES
  26. (0,"AUS_CHANGE","Auto Update Statistics Evaluation","10","NUMERIC",
  27. "The statistics are rebuilt after this percentage of data has changed.");
  28. INSERT INTO ph_threshold
  29. (id,name,task_name,value,value_type,description)
  30. VALUES
  31. (0,"AUS_AUTO_RULES","Auto Update Statistics Evaluation","1","NUMERIC",
  32. "Ensures a base set of guidelines are followed when building statistics.");
  33. INSERT INTO ph_threshold
  34. (id,name,task_name,value,value_type,description)
  35. VALUES
  36. (0,"AUS_SMALL_TABLES","Auto Update Statistics Evaluation","100","NUMERIC",
  37. "Tables containing less than this number of rows will always have their statistics rebuilt.");
  38. INSERT INTO ph_threshold
  39. (id,name,task_name,value,value_type,description)
  40. VALUES
  41. (0,"AUS_PDQ","Auto Update Statistics Refresh","10","NUMERIC",
  42. "Update statistics executes with this PDQ priority.");
  43. {*********************************************************
  44. *
  45. * The following section creates all the procedures
  46. * utilized by AUS
  47. *
  48. ********************************************************
  49. *}
  50. CREATE FUNCTION informix.aus_get_realtime()
  51. RETURNING DATETIME YEAR TO SECOND
  52. DEFINE cur_time DATETIME YEAR TO SECOND;
  53. LET cur_time = (SELECT
  54. DBINFO( 'utc_to_datetime',sh_curtime)::DATETIME YEAR TO SECOND
  55. FROM sysmaster:sysshmvals);
  56. RETURN cur_time;
  57. END FUNCTION;
  58. CREATE FUNCTION informix.aus_setup_mon_table_profile(task_id INTEGER, task_seq INTEGER,
  59. inHDRmode INTEGER)
  60. RETURNING INTEGER
  61. DEFINE task_cnt INTEGER;
  62. DEFINE index_cnt INTEGER;
  63. --TRACE "FUNCTION aus_setup_mon_table_profile()" ;
  64. -- Make sure the task mon_table_profile is there an active
  65. SELECT count(*)
  66. INTO task_cnt
  67. FROM ph_task
  68. WHERE tk_name ="mon_table_profile";
  69. -- Check to see if index exists on (id,partnum)
  70. SELECT count(*)
  71. INTO index_cnt
  72. FROM sysindices
  73. WHERE tabid = ( SELECT tabid FROM systables
  74. WHERE tabname = "mon_table_profile" )
  75. AND ABS(ikeyextractcolno(indexkeys,0)) =
  76. ( SELECT colno FROM syscolumns
  77. WHERE tabid = ( SELECT tabid FROM systables
  78. WHERE tabname = "mon_table_profile"
  79. )
  80. AND colname ='id'
  81. )
  82. AND ABS(ikeyextractcolno(indexkeys,1)) =
  83. ( SELECT colno FROM syscolumns
  84. WHERE tabid = ( SELECT tabid FROM systables
  85. WHERE tabname = "mon_table_profile"
  86. )
  87. AND colname ='partnum'
  88. );
  89. IF task_cnt < 1 THEN
  90. INSERT INTO ph_alert
  91. (ID, alert_task_id,alert_task_seq,alert_type,
  92. alert_color, alert_object_type,
  93. alert_object_name, alert_message,alert_action)
  94. VALUES
  95. (0,task_id, task_seq, "WARNING", "green",
  96. "SERVER","Auto Update Statistics",
  97. "Built in server task (mon_table_profile) is missing. " ||
  98. "Auto Update Statistics proceeding with limited information.",
  99. NULL);
  100. RETURN -1;
  101. END IF;
  102. IF index_cnt < 1 THEN
  103. INSERT INTO ph_alert
  104. (ID, alert_task_id,alert_task_seq,alert_type,
  105. alert_color, alert_object_type,
  106. alert_object_name, alert_message,alert_action)
  107. VALUES
  108. (0,task_id, task_seq, "INFO", "green",
  109. "SERVER","Auto Update Statistics",
  110. "Building index on table mon_table_profile to optimize performance for Auto Update Statistics." ,
  111. NULL);
  112. IF inHDRmode = 1 THEN
  113. CREATE INDEX mon_table_profile_sys_ix1
  114. ON mon_table_profile(id,partnum) ONLINE;
  115. ELSE
  116. CREATE INDEX mon_table_profile_sys_ix1
  117. ON mon_table_profile(id,partnum);
  118. END IF;
  119. END IF;
  120. RETURN 1;
  121. END FUNCTION;
  122. CREATE FUNCTION informix.aus_get_exclusive_access(task_id INTEGER, task_seq INTEGER)
  123. RETURNING INTEGER
  124. DEFINE errnum INTEGER;
  125. DEFINE cnt INTEGER;
  126. DEFINE lk_sid INTEGER;
  127. --TRACE "FUNCTION aus_get_exclusive_access()" ;
  128. BEGIN
  129. ON EXCEPTION IN ( -310 ) SET errnum
  130. SELECT count(*) , MAX(aus_lk_sid)
  131. INTO cnt, lk_sid
  132. FROM aus_work_lock, sysmaster:sysscblst
  133. WHERE aus_lk_sid = sid
  134. AND aus_lk_task_id = task_id
  135. AND aus_lk_task_seq = task_seq;
  136. --TRACE "CNT = " || cnt || "lock SID = "||lk_sid;
  137. IF cnt > 0 THEN
  138. RAISE EXCEPTION -777, -107,
  139. "Current AUS tables are in use by Session ID "||lk_sid;
  140. END IF
  141. -- Fall through if count equal zero
  142. DELETE FROM aus_work_lock;
  143. END EXCEPTION WITH RESUME
  144. CREATE TABLE aus_work_lock (
  145. aus_lk_sid INTEGER,
  146. aus_lk_task_id INTEGER,
  147. aus_lk_task_seq INTEGER );
  148. INSERT INTO aus_work_lock(aus_lk_sid,aus_lk_task_id,aus_lk_task_seq)
  149. VALUES
  150. (DBINFO('sessionid'),task_id,task_seq);
  151. END
  152. RETURN 0;
  153. END FUNCTION;
  154. CREATE FUNCTION informix.aus_rel_exclusive_access()
  155. RETURNING INTEGER
  156. --TRACE "FUNCTION aus_rel_exclusive_access()" ;
  157. BEGIN
  158. ON EXCEPTION IN ( -206, -310 )
  159. END EXCEPTION
  160. DROP TABLE aus_work_lock;
  161. END
  162. RETURN 0;
  163. END FUNCTION;
  164. CREATE FUNCTION informix.aus_cleanup_table( save_results INTEGER )
  165. RETURNING INTEGER
  166. DEFINE errnum INTEGER;
  167. DEFINE cnt INTEGER;
  168. --TRACE "FUNCTION aus_cleanup_table()" ;
  169. IF save_results = 0 THEN
  170. SELECT COUNT(*)
  171. INTO cnt
  172. FROM ph_task
  173. WHERE BITAND(tk_attributes, '0x200' ) > 0
  174. AND tk_name like "Auto Update Statistics Refresh%"
  175. AND tk_next_execution <= ( SELECT tk_next_execution
  176. FROM ph_task
  177. WHERE tk_name = "Auto Update Statistics Evaluation");
  178. IF cnt > 0 THEN
  179. RAISE EXCEPTION -214, -107, "Current AUS tables are in use";
  180. END IF
  181. END IF
  182. /* Cleanup all the work tables */
  183. BEGIN
  184. ON EXCEPTION IN ( -214, -206, -394 ) SET errnum
  185. -- non-exclusive access, & table does not exist
  186. IF errnum = -214 THEN
  187. RAISE EXCEPTION -214, -107, "Current AUS tables are in use";
  188. END IF
  189. -- If error is -206 ignore the error, tables have been dropped
  190. END EXCEPTION WITH RESUME
  191. DROP TABLE aus_work_icols;
  192. DROP TABLE aus_work_dist;
  193. DROP TABLE aus_work_info;
  194. IF save_results == 0 THEN
  195. DROP TABLE aus_work_icols;
  196. DROP TABLE aus_work_dist;
  197. DROP TABLE aus_work_info;
  198. DROP TABLE aus_cmd_info;
  199. DROP VIEW aus_cmd_list;
  200. DROP VIEW aus_cmd_comp;
  201. DROP TABLE aus_command; -- drop views also
  202. END IF
  203. END
  204. RETURN 1;
  205. END FUNCTION;
  206. CREATE FUNCTION informix.aus_setup_table(inHDRmode INTEGER)
  207. RETURNING integer
  208. DEFINE errnum INTEGER;
  209. --TRACE "FUNCTION aus_setup_table()" ;
  210. /* Cleanup all the work tables */
  211. BEGIN
  212. ON EXCEPTION IN ( -310 ) SET errnum -- table already exists
  213. END EXCEPTION WITH RESUME
  214. CREATE TABLE informix.aus_cmd_info
  215. (
  216. aus_ci_dbs_partnum INTEGER,
  217. aus_ci_stime DATETIME YEAR TO SECOND
  218. DEFAULT CURRENT YEAR TO SECOND,
  219. aus_ci_etime DATETIME YEAR TO SECOND
  220. DEFAULT NULL,
  221. aus_ci_database VARCHAR(255) DEFAULT NULL,
  222. aus_ci_locale VARCHAR(36) DEFAULT NULL,
  223. aus_ci_logmode CHAR(1) DEFAULT NULL,
  224. aus_ci_missed_tables INTEGER DEFAULT 0,
  225. aus_ci_need_tables INTEGER DEFAULT 0,
  226. aus_ci_done_tables INTEGER DEFAULT 0
  227. );
  228. INSERT INTO aus_cmd_info(aus_ci_dbs_partnum,aus_ci_stime)
  229. VALUES (0,aus_get_realtime());
  230. IF inHDRmode = 1 THEN
  231. CREATE UNIQUE INDEX informix.aus_cmd_info_index1
  232. ON aus_cmd_info(aus_ci_dbs_partnum) ONLINE;
  233. CREATE UNIQUE INDEX informix.aus_cmd_info_index2
  234. ON aus_cmd_info(aus_ci_database) ONLINE;
  235. ELSE
  236. CREATE UNIQUE INDEX informix.aus_cmd_info_index1
  237. ON aus_cmd_info(aus_ci_dbs_partnum);
  238. CREATE UNIQUE INDEX informix.aus_cmd_info_index2
  239. ON aus_cmd_info(aus_ci_database);
  240. END IF;
  241. CREATE TABLE informix.aus_command
  242. (
  243. aus_cmd_id SERIAL,
  244. aus_cmd_state CHAR(1) DEFAULT 'P'
  245. CHECK (aus_cmd_state IN ("P","I","E","C")),
  246. -- P => Command is pending
  247. -- I => Command is inprogress
  248. -- E => Command had an Error
  249. -- C => Command is complete w/o Errors
  250. aus_cmd_type CHAR(1),
  251. aus_cmd_dbs_priority SMALLINT DEFAULT 2,
  252. aus_cmd_priority BIGINT,
  253. aus_cmd_dbs_partnum INTEGER,
  254. aus_cmd_partnum INTEGER,
  255. aus_cmd_err_sql INTEGER,
  256. aus_cmd_err_isam INTEGER,
  257. aus_cmd_time DATETIME YEAR TO SECOND DEFAULT CURRENT YEAR TO SECOND,
  258. aus_cmd_runtime INTERVAL HOUR TO SECOND DEFAULT NULL,
  259. aus_cmd_exe LVARCHAR(8192)
  260. ) LOCK MODE ROW;
  261. CREATE VIEW informix.aus_cmd_list AS SELECT
  262. aus_cmd_id, aus_cmd_type,
  263. aus_cmd_priority, aus_cmd_dbs_partnum,
  264. aus_cmd_partnum, aus_cmd_exe
  265. FROM aus_command
  266. WHERE aus_cmd_state = 'P';
  267. CREATE VIEW informix.aus_cmd_comp AS SELECT
  268. aus_cmd_id, aus_cmd_type,
  269. aus_cmd_priority, aus_cmd_dbs_partnum,
  270. aus_cmd_partnum, aus_cmd_exe,
  271. aus_cmd_time
  272. FROM aus_command
  273. WHERE aus_cmd_state = 'C';
  274. END
  275. BEGIN
  276. ON EXCEPTION IN ( -310 ) SET errnum -- table already exists
  277. END EXCEPTION WITH RESUME
  278. /*
  279. * This table contains both
  280. * index columns as wells as
  281. * user defined distribution columns
  282. */
  283. CREATE TABLE informix.aus_work_icols
  284. (
  285. aus_icols_tabid integer,
  286. aus_icols_colno integer,
  287. aus_icols_lkey char(1) CHECK( aus_icols_lkey IN ('Y','N')),
  288. aus_icols_mode char(1) DEFAULT NULL,
  289. aus_icols_colname varchar(128)
  290. ) LOCK MODE ROW;
  291. CREATE TABLE informix.aus_work_info
  292. (
  293. aus_info_id SERIAL,
  294. aus_info_db_partnum INTEGER,
  295. aus_info_tabname VARCHAR(128),
  296. aus_info_tabid INTEGER,
  297. aus_info_partnum INTEGER,
  298. aus_info_ustlowts DATETIME YEAR TO SECOND,
  299. aus_info_npused BIGINT,
  300. aus_info_nrows BIGINT,
  301. aus_info_nindexes smallint
  302. ) LOCK MODE ROW;
  303. CREATE TABLE informix.aus_work_dist
  304. (
  305. aus_dist_id serial,
  306. aus_dist_tabid INTEGER, -- this is the tabid
  307. aus_dist_colno INTEGER,
  308. aus_dist_mode CHAR(1),
  309. aus_dist_resolution FLOAT,
  310. aus_dist_confidence FLOAT,
  311. aus_dist_smplsize float,
  312. aus_dist_rowssmplde BIGINT,
  313. aus_dist_constr_time DATETIME YEAR TO SECOND,
  314. aus_dist_ustnrows BIGINT
  315. ) LOCK MODE ROW;
  316. END
  317. RETURN 1;
  318. END FUNCTION;
  319. CREATE FUNCTION informix.aus_refresh_stats_orig( )
  320. RETURNING integer
  321. DEFINE rc INTEGER;
  322. DEFINE cnt INTEGER;
  323. DEFINE i INTEGER;
  324. LET rc=1;
  325. LET i=1;
  326. WHILE ( rc <> 0 ) LOOP
  327. LET rc = aus_refresh_stats_orig(-1,i);
  328. LET i=i+1;
  329. END LOOP;
  330. RETURN rc;
  331. END FUNCTION;
  332. CREATE FUNCTION informix.aus_refresh_stats_orig(task_id INTEGER, task_seq INTEGER)
  333. RETURNING integer
  334. DEFINE rc INTEGER;
  335. DEFINE cnt INTEGER;
  336. DEFINE del INTEGER;
  337. DEFINE t_partnum INTEGER;
  338. DEFINE last_partnum INTEGER;
  339. DEFINE t_dbs_partnum INTEGER;
  340. DEFINE last_dbs_partnum INTEGER;
  341. DEFINE t_id INTEGER;
  342. DEFINE t_type CHAR(1);
  343. DEFINE t_cmd CHAR(8192);
  344. DEFINE p_cmd CHAR(200);
  345. DEFINE t_priority BIGINT;
  346. DEFINE param_pdq INTEGER;
  347. --TRACE "FUNCTION aus_refresh_stats_orig";
  348. LET rc = 0;
  349. LET cnt = 0;
  350. LET del = 0;
  351. LET last_partnum = 0;
  352. LET t_partnum = NULL;
  353. --SET DEBUG FILE TO "/tmp/aus.refresh."||task_seq;
  354. --TRACE ON;
  355. -- Get the config thresholds
  356. SELECT MAX(value::integer) INTO param_pdq
  357. FROM sysadmin:ph_threshold WHERE name = "AUS_PDQ";
  358. IF param_pdq IS NULL THEN
  359. LET param_pdq = 0;
  360. ELIF param_pdq < 0 THEN
  361. LET param_pdq = 0;
  362. ELIF param_pdq > 100 THEN
  363. LET param_pdq = 100;
  364. END IF
  365. IF param_pdq > 0 AND is_pdq_allowed() > 0 THEN
  366. LET p_cmd = "SET PDQPRIORITY " ||param_pdq;
  367. END IF
  368. BEGIN
  369. ON EXCEPTION IN ( -206 ) -- Exit if aus_cmd_* tables are not found
  370. END EXCEPTION
  371. FOREACH SELECT --+ FIRST_ROWS
  372. aus_cmd_id, RTRIM(aus_cmd_exe),aus_cmd_partnum, aus_cmd_priority,
  373. aus_cmd_type, aus_cmd_dbs_partnum
  374. INTO
  375. t_id, t_cmd, t_partnum, t_priority, t_type , t_dbs_partnum
  376. FROM aus_command
  377. WHERE aus_cmd_state = 'P' -- Pending
  378. ORDER BY aus_cmd_priority DESC, aus_cmd_partnum, aus_cmd_type DESC
  379. --TRACE "LAST partnum ="||last_partnum;
  380. IF last_partnum == 0 THEN
  381. LET last_partnum = t_partnum;
  382. LET last_dbs_partnum = t_dbs_partnum;
  383. LET cnt = cnt + 1;
  384. ELIF last_partnum <> t_partnum THEN
  385. LET last_partnum = t_partnum;
  386. IF t_priority > 100000 THEN
  387. IF last_dbs_partnum <> t_dbs_partnum THEN
  388. CONTINUE FOREACH;
  389. END IF
  390. IF cnt > 100 THEN
  391. EXIT FOREACH;
  392. END IF
  393. LET cnt = cnt + 1;
  394. ELSE
  395. EXIT FOREACH;
  396. END IF
  397. END IF
  398. --TRACE "UPDATING cmd_id="||t_id ||" TABLE "|| t_partnum||" MODE " || RTRIM(t_type)::lvarchar ||" CNT =" ||cnt;
  399. DELETE FROM aus_command WHERE aus_cmd_id = t_id;
  400. LET del = DBINFO("sqlca.sqlerrd2");
  401. /* If we did not delete anything then skip this row, parallel */
  402. IF del < 0 THEN
  403. CONTINUE FOREACH;
  404. END IF
  405. BEGIN
  406. ON EXCEPTION IN ( -206 ) -- IGNORE if the table is gone
  407. END EXCEPTION WITH RESUME
  408. EXECUTE IMMEDIATE p_cmd;
  409. EXECUTE IMMEDIATE t_cmd;
  410. IF is_pdq_allowed() > 0 THEN
  411. SET PDQPRIORITY 0;
  412. END IF
  413. END
  414. INSERT INTO aus_command
  415. ( aus_cmd_id, aus_cmd_type, aus_cmd_priority, aus_cmd_state,
  416. aus_cmd_dbs_partnum, aus_cmd_partnum, aus_cmd_exe )
  417. VALUES
  418. ( t_id, t_type, t_priority, 'C', t_dbs_partnum, t_partnum, TRIM(t_cmd));
  419. LET rc=rc+1;
  420. END FOREACH
  421. IF cnt > 0 THEN
  422. UPDATE aus_cmd_info
  423. SET (aus_ci_done_tables) = (aus_ci_done_tables + cnt)
  424. WHERE aus_ci_dbs_partnum = last_dbs_partnum;
  425. ELIF task_id > 0 THEN
  426. /* I have no more work to and I am a real task disable my self */
  427. UPDATE ph_task SET ( tk_enable ) = ('F') WHERE tk_id = task_id;
  428. END IF
  429. END
  430. RETURN rc;
  431. END FUNCTION;
  432. CREATE FUNCTION informix.aus_enable_refresh()
  433. RETURNING INTEGER
  434. UPDATE ph_task SET ( tk_enable) =
  435. ('T')
  436. WHERE tk_name matches "Auto Update Statistics Refresh*";
  437. END FUNCTION;
  438. CREATE FUNCTION informix.aus_create_cmd_dist(dbsname char(128), dbs_partnum INTEGER,
  439. tabname CHAR(128), partnum INTEGER, tabid INTEGER,
  440. param_rules INTEGER, expire_priority BIGINT)
  441. RETURNING BIGINT
  442. DEFINE rc INTEGER;
  443. DEFINE cnt INTEGER;
  444. DEFINE collist CHAR(7600);
  445. DEFINE maxcollength INTEGER;
  446. DEFINE collistlen INTEGER;
  447. DEFINE collen INTEGER;
  448. DEFINE t_colno INTEGER;
  449. DEFINE t_resolution DECIMAL(5,3);
  450. DEFINE last_resolution DECIMAL(5,3);
  451. DEFINE t_confidence DECIMAL(5,3);
  452. DEFINE t_smplsize DECIMAL(16,3);
  453. DEFINE t_colname CHAR(128);
  454. DEFINE tmp CHAR(128);
  455. DEFINE lasttmp CHAR(128);
  456. DEFINE end_str CHAR(256);
  457. --TRACE "FUNCTION aus_create_cmd_dist( database=" || RTRIM(dbsname) || " tabid = " || tabid || " )" ;
  458. LET collist = NULL;
  459. LET rc = 0;
  460. /* Note the l must be lower case, so we
  461. * can order by later can get the order as
  462. * H, M, l
  463. * when building commands.
  464. */
  465. INSERT INTO aus_command
  466. ( aus_cmd_id, aus_cmd_type, aus_cmd_priority, aus_cmd_dbs_partnum, aus_cmd_partnum, aus_cmd_exe )
  467. VALUES
  468. ( 0, "l", expire_priority, dbs_partnum, partnum,
  469. "UPDATE STATISTICS LOW FOR TABLE " || RTRIM(dbsname) || ":"
  470. || RTRIM(tabname)
  471. );
  472. /* FIND ALL HIGH COLUMNS
  473. * The first part finds all column
  474. * which were previously in sysdistrib
  475. * The second part SQL is executed if
  476. * the auto rules are enable, it finds
  477. * the minimum set of columns for this
  478. * table for the optimizer
  479. */
  480. UPDATE aus_work_icols SET ( aus_icols_mode ) = ( 'H' )
  481. WHERE aus_icols_tabid = tabid
  482. AND aus_icols_colno in ( SELECT aus_dist_colno FROM aus_work_dist
  483. WHERE aus_dist_tabid = tabid
  484. AND aus_dist_mode = 'H');
  485. --TRACE "EXISTING HIGH ROWS UPDATED " || DBINFO("sqlca.sqlerrd2") || ")";
  486. IF param_rules > 0 THEN
  487. UPDATE aus_work_icols SET ( aus_icols_mode ) = ( decode(aus_icols_lkey,'Y','H','M') )
  488. WHERE aus_icols_tabid = tabid
  489. AND aus_icols_mode IS NULL;
  490. --TRACE "PARAM_RULES ROWS UPDATED " || DBINFO("sqlca.sqlerrd2") || ")";
  491. ELSE
  492. SELECT count(*) INTO cnt
  493. FROM aus_work_icols
  494. WHERE aus_icols_mode IS NULL AND aus_icols_tabid = tabid;
  495. IF cnt > 0 THEN
  496. UPDATE aus_cmd_info SET
  497. (aus_ci_missed_tables) = (aus_ci_missed_tables + 1)
  498. WHERE aus_ci_database = dbsname;
  499. END IF
  500. END IF
  501. /** HIGH COLUMNS **/
  502. LET collist = NULL;
  503. LET maxcollength = 7600;
  504. LET collistlen = 0;
  505. LET collen = 0;
  506. LET tmp = NULL;
  507. LET lasttmp = NULL;
  508. FOREACH SELECT
  509. aus_icols_colno, aus_icols_colname, NVL(aus_dist_resolution,0.5)
  510. INTO
  511. t_colno, t_colname, t_resolution
  512. FROM aus_work_icols , OUTER aus_work_dist
  513. WHERE aus_icols_tabid = aus_dist_tabid
  514. AND aus_icols_colno = aus_dist_colno
  515. AND aus_icols_tabid = tabid
  516. AND aus_icols_mode = 'H'
  517. ORDER BY aus_dist_resolution, aus_dist_colno
  518. IF collist IS NULL THEN
  519. LET collist = RTRIM(t_colname);
  520. LET collistlen = LENGTH(TRIM(collist));
  521. LET last_resolution = t_resolution;
  522. LET end_str = " RESOLUTION " || t_resolution || " DISTRIBUTIONS ONLY";
  523. ELIF last_resolution == t_resolution THEN
  524. LET collen = LENGTH(RTRIM(t_colname));
  525. -- TRACE "collist len: " || collistlen;
  526. IF collen + collistlen + 2 >= maxcollength THEN
  527. INSERT INTO aus_command
  528. ( aus_cmd_id, aus_cmd_type, aus_cmd_priority,
  529. aus_cmd_dbs_partnum, aus_cmd_partnum, aus_cmd_exe )
  530. VALUES
  531. ( 0, "H", expire_priority, dbs_partnum, partnum,
  532. "UPDATE STATISTICS HIGH FOR TABLE " || RTRIM(dbsname)
  533. || ":" || RTRIM(tabname)
  534. || " ( " || TRIM(collist) || " ) " || TRIM(end_str)
  535. );
  536. LET collist = RTRIM(t_colname);
  537. LET collistlen = LENGTH(TRIM(collist));
  538. ELSE
  539. LET collist = RTRIM(collist) || ", " ||
  540. RTRIM(t_colname);
  541. LET collistlen = collistlen + collen + 2;
  542. END IF
  543. ELSE
  544. INSERT INTO aus_command
  545. ( aus_cmd_id, aus_cmd_type, aus_cmd_priority,
  546. aus_cmd_dbs_partnum, aus_cmd_partnum, aus_cmd_exe )
  547. VALUES
  548. ( 0, "H", expire_priority, dbs_partnum, partnum,
  549. "UPDATE STATISTICS HIGH FOR TABLE " || RTRIM(dbsname)
  550. || ":" || RTRIM(tabname)
  551. || " ( " || TRIM(collist) || " ) " || TRIM(end_str)
  552. );
  553. LET collist = TRIM(t_colname);
  554. LET collistlen = LENGTH(TRIM(collist));
  555. LET end_str = " RESOLUTION " || t_resolution || " DISTRIBUTIONS ONLY";
  556. LET last_resolution = t_resolution;
  557. END IF
  558. --TRACE "COLLIST LENGTH: " || LENGTH(TRIM(collist));
  559. --TRACE "HIGH Colname " || RTRIM(t_colname);
  560. END FOREACH
  561. IF collist IS NOT NULL THEN
  562. INSERT INTO aus_command
  563. ( aus_cmd_id, aus_cmd_type, aus_cmd_priority,
  564. aus_cmd_dbs_partnum, aus_cmd_partnum, aus_cmd_exe )
  565. VALUES
  566. ( 0, "H", expire_priority, dbs_partnum, partnum,
  567. "UPDATE STATISTICS HIGH FOR TABLE "|| RTRIM(dbsname)
  568. || ":" || RTRIM(tabname)
  569. || " ( "|| RTRIM(collist) || " ) " || TRIM(end_str)
  570. );
  571. END IF
  572. /*
  573. -- FIND ALL MED COLUMNS
  574. */
  575. UPDATE aus_work_icols SET ( aus_icols_mode ) = ( 'M' )
  576. WHERE aus_icols_tabid = tabid
  577. AND aus_icols_colno in ( SELECT aus_dist_colno FROM aus_work_dist
  578. WHERE aus_dist_tabid = tabid
  579. AND aus_dist_mode = 'M');
  580. LET collist = NULL;
  581. LET collistlen = 0;
  582. LET collen = 0;
  583. LET tmp = NULL;
  584. LET lasttmp = NULL;
  585. FOREACH SELECT
  586. aus_icols_colno, aus_icols_colname,
  587. NVL(aus_dist_resolution,2.0), NVL(aus_dist_confidence,0.95),
  588. NVL(aus_dist_smplsize,0.0),
  589. NVL(aus_dist_smplsize,0)::DECIMAL(16,3) || "_" ||
  590. NVL(aus_dist_resolution,0)::DECIMAL(5,2) || "_" ||
  591. NVL(aus_dist_confidence,0)::DECIMAL(4,2) AS C
  592. INTO
  593. t_colno, t_colname,
  594. t_resolution, t_confidence,
  595. t_smplsize, tmp
  596. FROM aus_work_icols , OUTER aus_work_dist
  597. WHERE aus_icols_tabid = aus_dist_tabid
  598. AND aus_icols_colno = aus_dist_colno
  599. AND aus_icols_tabid = tabid
  600. AND aus_icols_mode = 'M'
  601. ORDER BY C, aus_dist_colno
  602. --TRACE "MED Colname " || RTRIM(t_colname) || " tmp" || RTRIM(tmp);
  603. --TRACE "collist " || TRIM(NVL(collist,"NULL"));
  604. --TRACE "lasttmp " || TRIM(NVL(lasttmp,"NULL"));
  605. --TRACE "tmp " || TRIM(NVL(tmp,"NULL"));
  606. IF collist IS NULL THEN
  607. LET collist = TRIM(t_colname);
  608. LET collistlen = LENGTH(TRIM(collist));
  609. LET lasttmp = tmp;
  610. LET end_str = decode(t_smplsize,0.0," "," SAMPLING SIZE "
  611. || t_smplsize )
  612. || " RESOLUTION "|| t_resolution
  613. || " " || t_confidence
  614. || " DISTRIBUTIONS ONLY";
  615. --TRACE "NULL collist" || TRIM(t_colname) || " tmp" || TRIM(tmp);
  616. ELIF lasttmp IS NULL OR lasttmp == tmp THEN
  617. --TRACE "equal collist" || TRIM(t_colname) || " tmp" || TRIM(tmp);
  618. LET collen = LENGTH(RTRIM(t_colname));
  619. --TRACE "collist len: " || collistlen;
  620. IF collen + collistlen + 2 >= maxcollength THEN
  621. INSERT INTO aus_command
  622. ( aus_cmd_id, aus_cmd_type, aus_cmd_priority,
  623. aus_cmd_dbs_partnum, aus_cmd_partnum, aus_cmd_exe )
  624. VALUES
  625. ( 0, "M", expire_priority, dbs_partnum, partnum,
  626. "UPDATE STATISTICS MEDIUM FOR TABLE "
  627. || RTRIM(dbsname) || ":" || TRIM(tabname)
  628. || " (" || TRIM(collist) || ") " || TRIM(end_str)
  629. );
  630. LET collist = RTRIM(t_colname);
  631. LET collistlen = LENGTH(TRIM(collist));
  632. ELSE
  633. LET collist = RTRIM(collist) || ", "
  634. || RTRIM(t_colname);
  635. LET collistlen = collistlen + collen + 2;
  636. END IF
  637. ELSE
  638. INSERT INTO aus_command
  639. ( aus_cmd_id, aus_cmd_type, aus_cmd_priority,
  640. aus_cmd_dbs_partnum, aus_cmd_partnum, aus_cmd_exe )
  641. VALUES
  642. ( 0, "M", expire_priority, dbs_partnum, partnum,
  643. "UPDATE STATISTICS MEDIUM FOR TABLE " || RTRIM(dbsname)
  644. || ":" || TRIM(tabname)
  645. || " ("|| TRIM(collist) || ") " || TRIM(end_str)
  646. );
  647. LET collist = TRIM(t_colname);
  648. LET collistlen = LENGTH(TRIM(collist));
  649. LET lasttmp = tmp;
  650. LET end_str = decode(t_smplsize,0.0," "," SAMPLING SIZE "
  651. || t_smplsize )
  652. || " RESOLUTION " || t_resolution
  653. || " " || t_confidence
  654. || " DISTRIBUTIONS ONLY";
  655. END IF
  656. --TRACE "MED Colname " || TRIM(t_colname);
  657. END FOREACH
  658. IF collist IS NOT NULL THEN
  659. INSERT INTO aus_command
  660. ( aus_cmd_id, aus_cmd_type, aus_cmd_priority,
  661. aus_cmd_dbs_partnum, aus_cmd_partnum, aus_cmd_exe )
  662. VALUES
  663. ( 0, "M", expire_priority, dbs_partnum, partnum,
  664. "UPDATE STATISTICS MEDIUM FOR TABLE " ||
  665. TRIM(dbsname) || ":" || TRIM(tabname)
  666. || " (" || TRIM(collist) || ") " || TRIM(end_str)
  667. );
  668. END IF
  669. RETURN 0;
  670. END FUNCTION;
  671. CREATE FUNCTION informix.aus_evaluator_dbs(dbsname CHAR(128), dbs_partnum INTEGER,
  672. has_mon_tab_prof INTEGER, inHDRmode INTEGER)
  673. RETURNING integer
  674. DEFINE aus_if_id INTEGER;
  675. DEFINE aus_if_tabname CHAR(128);
  676. DEFINE aus_if_tabid INTEGER;
  677. DEFINE aus_if_partnum INTEGER;
  678. DEFINE aus_if_ustlowts DATETIME YEAR TO SECOND;
  679. DEFINE aus_if_npused BIGINT;
  680. DEFINE aus_if_nrows BIGINT;
  681. DEFINE aus_real_rows BIGINT;
  682. DEFINE aus_if_nindexes INTEGER;
  683. DEFINE oldest_time DATETIME YEAR TO SECOND;
  684. DEFINE expired_value BIGINT;
  685. DEFINE max_seq_id INTEGER;
  686. DEFINE min_seq_id INTEGER;
  687. DEFINE hours_expired BIGINT;
  688. DEFINE nrows, isreads, iswrite, isrwrite, isdelete FLOAT;
  689. DEFINE delta_time BIGINT;
  690. DEFINE small_tab_exp BIGINT;
  691. DEFINE tmin BIGINT;
  692. DEFINE tmp BIGINT;
  693. DEFINE param_age_stats INTEGER; -- Number of hours
  694. DEFINE param_change INTEGER;
  695. DEFINE param_rules INTEGER;
  696. DEFINE param_small_tab BIGINT;
  697. DEFINE row_count INTEGER;
  698. DEFINE cmd CHAR(1000);
  699. --TRACE "FUNCTION aus_evaluator_dbs(database="||TRIM(dbsname)::lvarchar||")" ;
  700. -- Get the config thresholds
  701. SELECT MAX(value::float * 24)::integer INTO param_age_stats
  702. FROM sysadmin:ph_threshold WHERE name = "AUS_AGE";
  703. SELECT MAX(value::integer) INTO param_change
  704. FROM sysadmin:ph_threshold WHERE name = "AUS_CHANGE";
  705. SELECT MAX(value::integer) INTO param_rules
  706. FROM sysadmin:ph_threshold WHERE name = "AUS_AUTO_RULES";
  707. SELECT MAX(value::bigint) INTO param_small_tab
  708. FROM sysadmin:ph_threshold WHERE name = "AUS_SMALL_TABLES";
  709. /* Default values if not found in the config table */
  710. LET param_age_stats = NVL(param_age_stats ,30*24);
  711. LET param_change = NVL(param_change ,10);
  712. LET param_rules = NVL(param_rules ,1);
  713. LET param_small_tab = NVL(param_small_tab ,100);
  714. IF param_small_tab > 200000 THEN
  715. /* Can not let be higher than 200,000 as
  716. * will cause overflow of variable
  717. */
  718. LET param_small_tab = 200000;
  719. END IF
  720. LET row_count = 0;
  721. /* Loop through the specified database */
  722. FOREACH SELECT
  723. aus_info_id, aus_info_tabname, aus_info_tabid,
  724. aus_info_partnum, aus_info_ustlowts, aus_info_npused,
  725. aus_info_nrows, aus_info_nindexes
  726. INTO
  727. aus_if_id, aus_if_tabname, aus_if_tabid,
  728. aus_if_partnum, aus_if_ustlowts, aus_if_npused,
  729. aus_if_nrows, aus_if_nindexes
  730. FROM aus_work_info
  731. WHERE aus_info_db_partnum = dbs_partnum
  732. ORDER BY aus_info_ustlowts
  733. IF aus_if_partnum = 0 THEN
  734. LET cmd = "UPDATE aus_work_info SET (aus_info_nrows) = ("
  735. || " (SELECT sum(pt.nrows)"
  736. || " FROM sysmaster:sysptnhdr pt"
  737. || " WHERE pt.partnum IN (SELECT partn FROM "
  738. || TRIM(dbsname)::lvarchar||":sysfragments sfg"
  739. || " WHERE sfg.tabid = " || aus_if_tabid
  740. || " AND sfg.fragtype = 'T')))"
  741. || " WHERE aus_info_tabid = " || aus_if_tabid ;
  742. EXECUTE IMMEDIATE cmd;
  743. LET cmd = "UPDATE aus_work_info"
  744. || " SET(aus_info_partnum) = ((SELECT min(lockid)"
  745. || " FROM sysmaster:sysptnhdr ptn, "
  746. || TRIM(dbsname)::lvarchar||":sysfragments"
  747. || " sfg WHERE ptn.partnum = sfg.partn"
  748. || " AND sfg.tabid = " || aus_if_tabid
  749. || " AND sfg.fragtype = 'T' ))"
  750. || " WHERE aus_info_tabid = " || aus_if_tabid ;
  751. EXECUTE IMMEDIATE cmd;
  752. SELECT aus_info_nrows
  753. INTO aus_real_rows
  754. FROM aus_work_info
  755. WHERE aus_info_tabid = aus_if_tabid;
  756. ELSE
  757. SELECT sum(pt.nrows)
  758. INTO aus_real_rows
  759. FROM sysmaster:sysptnhdr pt
  760. WHERE pt.partnum = aus_if_partnum;
  761. END IF
  762. --TRACE "Checking table "||TRIM(dbsname)::lvarchar||"." || TRIM(aus_if_tabname)::lvarchar;
  763. --TRACE "Number of rows "||aus_real_rows;
  764. LET expired_value = 0;
  765. /* If the table is considered a small row table
  766. * expire the table and create the commands.
  767. */
  768. LET tmp = param_small_tab - aus_real_rows;
  769. IF tmp > 0 THEN
  770. LET small_tab_exp = tmp + 10000 * param_small_tab;
  771. ELSE
  772. LET small_tab_exp = 0;
  773. END IF
  774. /* Calculate the oldesttime between
  775. * the statistics and distributions
  776. */
  777. SELECT MIN(aus_dist_constr_time)
  778. INTO oldest_time
  779. FROM aus_work_dist
  780. WHERE aus_dist_tabid = aus_if_tabid
  781. AND aus_dist_constr_time IS NOT NULL ;
  782. IF oldest_time IS NULL AND aus_if_ustlowts IS NULL THEN
  783. --TRACE "No Statistics and distributions for "|| TRIM(dbsname)::lvarchar||"." || TRIM(aus_if_tabname)::lvarchar;
  784. IF param_rules == 0 THEN
  785. /* If we have no stats or dist and we are not
  786. * doing auto rules then continue to the next table
  787. */
  788. UPDATE aus_cmd_info SET
  789. (aus_ci_missed_tables) = (aus_ci_missed_tables + 1)
  790. WHERE aus_ci_dbs_partnum = dbs_partnum;
  791. CONTINUE FOREACH;
  792. ELIF small_tab_exp == 0 THEN
  793. /* We have auto rules on, but this tables is not small.
  794. */
  795. LET expired_value = 100;
  796. ELSE
  797. /* We have auto rules on, and a small table
  798. */
  799. LET expired_value = small_tab_exp;
  800. END IF
  801. GOTO do_commands;
  802. END IF
  803. IF oldest_time IS NULL THEN
  804. LET oldest_time = aus_if_ustlowts;
  805. ELIF (aus_if_ustlowts IS NOT NULL) AND (aus_if_ustlowts < oldest_time) THEN
  806. LET oldest_time = aus_if_ustlowts;
  807. END IF
  808. --TRACE "Oldest time for table "|| TRIM(aus_if_tabname)::lvarchar || " is "|| oldest_time;
  809. /* If we have a small table and
  810. * we have any stats or dist OR we are doing auto rules
  811. * THEN goto make the commands
  812. */
  813. IF (small_tab_exp > 0) AND
  814. ( oldest_time IS NOT NULL OR param_rules <> 0 ) THEN
  815. LET expired_value = small_tab_exp;
  816. GOTO do_commands;
  817. END IF
  818. /* If we are not applying basic rules
  819. * and we have no upd stats low information
  820. * for this table before then skip
  821. * this table now and look for distributions.
  822. */
  823. IF param_rules == 0 AND (aus_if_nrows IS NULL OR aus_if_ustlowts IS NULL) THEN
  824. GOTO do_distribution_eval;
  825. END IF
  826. /*
  827. * Check the age of the statistics
  828. * If never been done then assign 100
  829. */
  830. --TRACE "Start statistics checking basic row count " || expired_value;
  831. --TRACE "aus_if_nrows "|| NVL(aus_if_nrows,"NULL");
  832. --TRACE "aus_real_rows "|| NVL(aus_real_rows,"NULL");
  833. IF aus_if_nrows IS NULL OR aus_real_rows IS NULL THEN
  834. LET expired_value = expired_value + 100;
  835. ELSE
  836. LET tmp = (aus_real_rows - aus_if_nrows) / (aus_if_nrows+1) * 100;
  837. --TRACE "Change in basic row count " || tmp ||"%";
  838. IF ABS(tmp) > param_change THEN
  839. LET expired_value = expired_value + ABS(tmp);
  840. END IF
  841. END IF
  842. /*
  843. * Check the basic row count of the statistics
  844. * If never been done then assign 100
  845. */
  846. --TRACE "Start statistics checking for age " || expired_value ;
  847. IF oldest_time IS NULL THEN
  848. LET expired_value = expired_value + 100;
  849. ELSE
  850. --TRACE "param_age_stats "||param_age_stats;
  851. LET hours_expired = (
  852. ( ( (CURRENT - oldest_time)::INTERVAL HOUR(5) TO HOUR
  853. - param_age_stats UNITS HOUR))::char(20))::BIGINT;
  854. --TRACE "hours_expired "||hours_expired;
  855. IF hours_expired > 0 THEN
  856. LET expired_value = expired_value + hours_expired/24;
  857. END IF
  858. END IF
  859. --TRACE "INFO statistics checking basic row count END " || expired_value;
  860. <<do_distribution_eval>>
  861. --TRACE "Statitics checking advanced row count START " || expired_value;
  862. IF oldest_time IS NOT NULL AND has_mon_tab_prof == 1 THEN
  863. -- Find the MAX/MIN sequence numbers to use for this table statistics
  864. -- Currently we do not take into account onstat -z
  865. SELECT MAX(run.run_task_seq),
  866. MIN(run.run_task_seq),
  867. ((((MAX(run.run_time) - MIN(run.run_time))::
  868. INTERVAL MINUTE(9) TO MINUTE)::char(20))::BIGINT)
  869. INTO max_seq_id, min_seq_id, delta_time
  870. FROM ph_run run, ph_task task
  871. WHERE task.tk_id = run.run_task_id
  872. AND tk_name = "mon_table_profile"
  873. AND run.run_time > oldest_time;
  874. --TRACE "Delta Time "|| delta_time ||" max task_seq "||max_seq_id||" min task_seq "||min_seq_id;
  875. /* If we had 0 or 1 measurement then delta_time will be 0
  876. * we must skip this check, not enough data
  877. */
  878. IF delta_time > 0 THEN
  879. LET tmin = (((CURRENT - oldest_time)::
  880. INTERVAL MINUTE(9) TO MINUTE)::char(20))::BIGINT;
  881. { Get the number of UDIS for statistics }
  882. --TRACE "SELECT " || aus_if_partnum ;
  883. SELECT
  884. tmin * ((SUM(aft.nrows) - SUM(bef.nrows))/delta_time),
  885. tmin * ((SUM(aft.pf_isread) - SUM(bef.pf_isread))/delta_time),
  886. tmin * ((SUM(aft.pf_iswrite) - SUM(bef.pf_iswrite))/delta_time),
  887. tmin * ((SUM(aft.pf_isrwrite) - SUM(bef.pf_isrwrite))/delta_time),
  888. tmin * ((SUM(aft.pf_isdelete) - SUM(bef.pf_isdelete))/delta_time)
  889. INTO nrows, isreads, iswrite, isrwrite, isdelete
  890. FROM mon_table_profile bef, mon_table_profile aft
  891. WHERE aft.id = max_seq_id
  892. AND bef.id = min_seq_id
  893. AND aft.lockid = aus_if_partnum
  894. AND bef.lockid = aus_if_partnum
  895. AND bef.lockid = aft.lockid;
  896. --TRACE "Inserts " || iswrite || "Update " || isrwrite|| "Delete " || isdelete;
  897. LET tmp = (iswrite + isrwrite + isdelete) - ( aus_real_rows * param_change/100);
  898. --TRACE "Rows Changed " || (iswrite + isrwrite + isdelete) || " Precent Changed " || (iswrite + isrwrite + isdelete) / aus_real_rows ;
  899. IF tmp > 0 THEN
  900. LET expired_value = expired_value + 100 + tmp;
  901. END IF
  902. END IF
  903. END IF
  904. /*
  905. * DONE calculating the statistics ranking
  906. */
  907. IF expired_value == 0 THEN
  908. CONTINUE FOREACH;
  909. END IF
  910. <<do_commands>>
  911. --TRACE "Building stats on table "||TRIM(dbsname)::lvarchar||"." || TRIM(aus_if_tabname)::lvarchar;
  912. /* Build the update low stats command if required */
  913. LET tmp = aus_create_cmd_dist(dbsname, dbs_partnum, aus_if_tabname,
  914. aus_if_partnum, aus_if_tabid,
  915. param_rules , expired_value );
  916. --TRACE "NEW CMD row_count="||row_count;
  917. IF tmp < 0 THEN
  918. RETURN tmp;
  919. END IF
  920. LET row_count = row_count + 1;
  921. END FOREACH --- End aus_dbs_list FOREACH
  922. RETURN row_count;
  923. END FUNCTION;
  924. CREATE FUNCTION informix.aus_load_dbs_data(aus_dbsname CHAR(128), aus_dbs_partnum INTEGER
  925. ,inHDRmode INTEGER)
  926. RETURNING bigint
  927. DEFINE tmp CHAR(1500);
  928. DEFINE nrows BIGINT;
  929. DEFINE drows BIGINT;
  930. LET nrows = 0;
  931. LET drows = 0;
  932. /*
  933. ***********************************************************
  934. * Load the aus_work_info table from systables
  935. ************************************************************
  936. */
  937. LET tmp = "INSERT INTO aus_work_info ("
  938. || " aus_info_id, aus_info_tabname, aus_info_tabid, aus_info_partnum, "
  939. || " aus_info_ustlowts, aus_info_npused, aus_info_nrows, "
  940. || " aus_info_nindexes, aus_info_db_partnum "
  941. || " ) SELECT "
  942. || " 0, tabname, tabid, partnum, "
  943. || " ustlowts, npused, nrows, "
  944. || " nindexes, "
  945. || aus_dbs_partnum
  946. || " FROM "
  947. || TRIM(aus_dbsname)::lvarchar||":systables t "
  948. || " WHERE "
  949. || " t.tabtype='T'"
  950. ;
  951. EXECUTE IMMEDIATE tmp ;
  952. --TRACE "Loading "||TRIM(aus_dbsname)::lvarchar||":aus_work_info with ROWS(" || DBINFO("sqlca.sqlerrd2")||")";
  953. LET nrows = nrows + DBINFO("sqlca.sqlerrd2");
  954. IF (aus_dbsname == "sysadmin") THEN
  955. DELETE FROM aus_work_info WHERE aus_info_tabname LIKE "aus_work_%"
  956. AND aus_info_db_partnum = aus_dbs_partnum;
  957. LET nrows = nrows - 4;
  958. END IF;
  959. IF inHDRmode = 1 THEN
  960. CREATE INDEX informix.aus_work_info_idx1 ON aus_work_info(aus_info_tabid)
  961. ONLINE;
  962. CREATE INDEX informix.aus_work_info_idx2 ON aus_work_info(aus_info_partnum)
  963. ONLINE;
  964. ELSE
  965. CREATE INDEX informix.aus_work_info_idx1 ON aus_work_info(aus_info_tabid);
  966. CREATE INDEX informix.aus_work_info_idx2 ON aus_work_info(aus_info_partnum);
  967. END IF
  968. /*
  969. ***********************************************************
  970. * Load the aus_work_dist table from sysdistrib table
  971. ************************************************************
  972. */
  973. LET tmp = "INSERT INTO aus_work_dist ("
  974. || " aus_dist_id, aus_dist_tabid, aus_dist_colno, "
  975. || " aus_dist_mode, aus_dist_resolution, aus_dist_confidence, "
  976. || " aus_dist_smplsize, aus_dist_rowssmplde, aus_dist_constr_time, "
  977. || " aus_dist_ustnrows "
  978. || " ) SELECT "
  979. || " 0, tabid, colno, "
  980. || " mode, resolution, confidence, "
  981. || " smplsize,rowssmpld,constr_time, "
  982. || " ustnrows"
  983. || " FROM " || TRIM(aus_dbsname)::lvarchar||":sysdistrib d "
  984. || " WHERE d.seqno=1 "
  985. ;
  986. EXECUTE IMMEDIATE tmp ;
  987. LET drows = drows + DBINFO("sqlca.sqlerrd2");
  988. IF inHDRmode = 1 THEN
  989. CREATE INDEX informix.aus_work_dist_idx1 ON aus_work_dist
  990. (aus_dist_tabid,aus_dist_colno) ONLINE;
  991. ELSE
  992. CREATE INDEX informix.aus_work_dist_idx1 ON aus_work_dist
  993. (aus_dist_tabid,aus_dist_colno);
  994. END IF
  995. --TRACE "Loading "||TRIM(aus_dbsname)::lvarchar||":aus_work_dist with ROWS(" || DBINFO("sqlca.sqlerrd2")||")";
  996. /* We need to update the fragment tables partnum with
  997. * the lock id, so we can reference them as one item.
  998. * Also get the current number of rows.
  999. UPDATE aus_work_info
  1000. SET ( aus_info_partnum, aus_info_nrows) =
  1001. ( ( SELECT MAX(lockid), SUM(nrows)
  1002. FROM sysmaster:systabnames t, sysmaster:sysptnhdr pt
  1003. WHERE t.partnum = pt.partnum
  1004. AND t.partnum = aus_info_partnum
  1005. AND t.tabname = aus_info_tabname
  1006. AND t.dbsname = aus_dbsname) )
  1007. WHERE aus_info_db_partnum = aus_dbs_partnum
  1008. AND aus_info_nrows = -1
  1009. ;
  1010. */
  1011. /*
  1012. ***********************************************************
  1013. * Load the aus_work_icols table of all index colnames
  1014. ************************************************************
  1015. */
  1016. LET tmp = "CREATE VIEW informix.aus_view (tabid,colno, colname,lkey) AS "
  1017. || " SELECT "
  1018. || " C.tabid, C.colno, MAX(C.colname), 'N' "
  1019. || " FROM "
  1020. || TRIM(aus_dbsname)::lvarchar||":syscolumns AS C, "
  1021. || TRIM(aus_dbsname)::lvarchar||":sysindices AS I "
  1022. || " WHERE "
  1023. || " C.tabid = I.tabid "
  1024. || " AND C.colno in "
  1025. || " (ABS(ikeyextractcolno(indexkeys,0)), "
  1026. || " ABS(ikeyextractcolno(indexkeys,1)) , "
  1027. || " ABS(ikeyextractcolno(indexkeys,2)) , "
  1028. || " ABS(ikeyextractcolno(indexkeys,3)) , "
  1029. || " ABS(ikeyextractcolno(indexkeys,4)) , "
  1030. || " ABS(ikeyextractcolno(indexkeys,5)) , "
  1031. || " ABS(ikeyextractcolno(indexkeys,6)) , "
  1032. || " ABS(ikeyextractcolno(indexkeys,7)) , "
  1033. || " ABS(ikeyextractcolno(indexkeys,8)) , "
  1034. || " ABS(ikeyextractcolno(indexkeys,9)) , "
  1035. || " ABS(ikeyextractcolno(indexkeys,10)) , "
  1036. || " ABS(ikeyextractcolno(indexkeys,11)) , "
  1037. || " ABS(ikeyextractcolno(indexkeys,12)) , "
  1038. || " ABS(ikeyextractcolno(indexkeys,13)) , "
  1039. || " ABS(ikeyextractcolno(indexkeys,14)) , "
  1040. || " ABS(ikeyextractcolno(indexkeys,15)) ) "
  1041. || " GROUP BY 1,2,4 "
  1042. || "UNION "
  1043. || "SELECT "
  1044. || " C.tabid, C.colno, MAX(C.colname), 'N' "
  1045. || " FROM "
  1046. || TRIM(aus_dbsname)::lvarchar||":syscolumns AS C, "
  1047. || "aus_work_dist AS D "
  1048. || " WHERE C.tabid = D.aus_dist_tabid "
  1049. || " AND C.colno = D.aus_dist_colno"
  1050. || " GROUP BY 1,2,4 "
  1051. ;
  1052. EXECUTE IMMEDIATE tmp ;
  1053. LET tmp = "INSERT INTO aus_work_icols"
  1054. || "(aus_icols_tabid, aus_icols_colno,aus_icols_colname,aus_icols_lkey) "
  1055. || " SELECT tabid, colno, colname,lkey FROM aus_view";
  1056. EXECUTE IMMEDIATE tmp ;
  1057. --TRACE "Loading "||TRIM(aus_dbsname)::lvarchar||":aus_work_icols with ROWS(" || DBINFO("sqlca.sqlerrd2")||")";
  1058. DROP VIEW aus_view;
  1059. IF inHDRmode = 1 THEN
  1060. CREATE INDEX informix.aus_work_icols_idx1 ON aus_work_icols
  1061. (aus_icols_tabid,aus_icols_colno) ONLINE;
  1062. ELSE
  1063. CREATE INDEX informix.aus_work_icols_idx1 ON aus_work_icols
  1064. (aus_icols_tabid,aus_icols_colno);
  1065. END IF
  1066. LET tmp = "UPDATE aus_work_icols SET aus_icols_lkey = 'Y' "
  1067. || "WHERE aus_icols_tabid*65536 + aus_icols_colno "
  1068. || " IN ( "
  1069. || " SELECT tabid*65536 + ABS(ikeyextractcolno(indexkeys,0)) "
  1070. || "FROM " || TRIM(aus_dbsname)::lvarchar||":sysindices)";
  1071. EXECUTE IMMEDIATE tmp ;
  1072. --TRACE "Updating lead keys for aus_work_icols," || DBINFO("sqlca.sqlerrd2")||" lead keys found";
  1073. RETURN nrows;
  1074. END FUNCTION;
  1075. CREATE FUNCTION informix.aus_evaluator(eval_only BOOLEAN)
  1076. RETURNING BIGINT
  1077. IF eval_only THEN
  1078. RETURN aus_evaluator(-1, 1, 0);
  1079. END IF
  1080. RETURN aus_evaluator(-1, 1, 1);
  1081. END FUNCTION;
  1082. CREATE FUNCTION informix.aus_evaluator(task_id INTEGER, task_seq INTEGER)
  1083. RETURNING BIGINT
  1084. RETURN aus_evaluator( task_id, task_seq, 1);
  1085. END FUNCTION;
  1086. CREATE FUNCTION informix.aus_evaluator(task_id INTEGER, task_seq INTEGER,myflags INTEGER)
  1087. RETURNING BIGINT
  1088. DEFINE aus_dbsname CHAR(128);
  1089. DEFINE aus_dbs_partnum INTEGER;
  1090. DEFINE trows BIGINT;
  1091. DEFINE nrows BIGINT;
  1092. DEFINE has_mon_tab_prof INTEGER;
  1093. DEFINE param_debug CHAR(128);
  1094. DEFINE dblocale CHAR(36);
  1095. DEFINE logmode CHAR(3);
  1096. DEFINE errnum INTEGER;
  1097. DEFINE inHDRmode INTEGER;
  1098. LET nrows = 0;
  1099. LET trows = 0;
  1100. SELECT FIRST 1 value INTO param_debug
  1101. FROM sysadmin:ph_threshold WHERE name = "AUS_DEBUG";
  1102. IF param_debug IS NOT NULL THEN
  1103. --SET DEBUG FILE TO TRIM(param_debug)::lvarchar||".prc";
  1104. --TRACE PROCEDURE;
  1105. --TRACE ON;
  1106. ELSE
  1107. --SET DEBUG FILE TO "/tmp/aus.debug.off";
  1108. --TRACE OFF;
  1109. --TRACE ON;
  1110. END IF
  1111. LET errnum = aus_get_exclusive_access(task_id, task_seq);
  1112. LET errnum = aus_cleanup_table(0);
  1113. SELECT FIRST 1 DECODE(type, "Primary", 1, "Standard", 0, 0) INTO inHDRmode
  1114. FROM sysmaster:sysdri;
  1115. IF (inHDRmode = 1) THEN
  1116. SET LOCK MODE TO WAIT 120;
  1117. ELSE
  1118. SET LOCK MODE TO WAIT 5;
  1119. END IF
  1120. LET errnum = aus_setup_table(inHDRmode);
  1121. SET ISOLATION TO DIRTY READ;
  1122. LET has_mon_tab_prof = aus_setup_mon_table_profile(task_id,task_seq,inHDRmode);
  1123. IF has_mon_tab_prof == 1 THEN
  1124. LET nrows = exectask( "mon_table_profile" );
  1125. END IF
  1126. /* Loop through all the logging databases
  1127. * loading up the aus_work_info table
  1128. */
  1129. --TRACE "Begin examining each logging database";
  1130. FOREACH SELECT TRIM(name), partnum
  1131. INTO aus_dbsname, aus_dbs_partnum
  1132. FROM sysmaster:sysdbspartn
  1133. WHERE partnum NOT IN
  1134. (select partnum
  1135. FROM sysmaster:sysdbspartn
  1136. WHERE bitand(flags, 3 ) > 0
  1137. AND name NOT IN (SELECT value FROM sysadmin:ph_threshold
  1138. WHERE name = "AUS_DATABASE_DISABLED" ))
  1139. INSERT INTO ph_alert
  1140. (ID, alert_task_id,alert_task_seq,alert_type,
  1141. alert_color, alert_object_type,
  1142. alert_object_name, alert_message,alert_action)
  1143. VALUES
  1144. (0,task_id, task_seq, "INFO", "yellow", "DATABASE",
  1145. "Auto Update Statistics",
  1146. "Skipping database ["||trim(aus_dbsname)||
  1147. "] for Auto Update Statistics. ",
  1148. NULL);
  1149. END FOREACH
  1150. FOREACH SELECT TRIM(D.name), D.partnum,
  1151. decode(bitand(D.flags,5),0,'N',4,'A','L') as logmode, T.collate
  1152. INTO aus_dbsname, aus_dbs_partnum, logmode, dblocale
  1153. FROM sysmaster:sysdbspartn D, sysmaster:systabnames T
  1154. WHERE bitand(D.flags, 3 ) > 0 --- Not ansi yet need owner names
  1155. AND D.name <> "sysmaster"
  1156. AND D.partnum = T.partnum
  1157. AND D.name NOT IN (SELECT value FROM sysadmin:ph_threshold
  1158. WHERE name = "AUS_DATABASE_DISABLED" )
  1159. INSERT INTO aus_cmd_info
  1160. (aus_ci_dbs_partnum, aus_ci_need_tables,
  1161. aus_ci_database, aus_ci_locale, aus_ci_logmode, aus_ci_stime)
  1162. VALUES
  1163. (aus_dbs_partnum, 0,
  1164. aus_dbsname, dblocale, logmode, aus_get_realtime());
  1165. --TRACE "Starting database loading " || RTRIM(aus_dbsname);
  1166. LET nrows = aus_load_dbs_data(aus_dbsname, aus_dbs_partnum, inHDRmode);
  1167. --TRACE "Starting database evaluation";
  1168. LET trows = aus_evaluator_dbs(aus_dbsname, aus_dbs_partnum,
  1169. has_mon_tab_prof, inHDRmode);
  1170. UPDATE aus_cmd_info
  1171. SET (aus_ci_need_tables,aus_ci_etime) =
  1172. (aus_ci_need_tables + trows, aus_get_realtime())
  1173. WHERE aus_ci_database = aus_dbsname;
  1174. IF trows < 0 THEN
  1175. EXIT FOREACH;
  1176. END IF
  1177. IF trows > 0 THEN
  1178. INSERT INTO ph_alert
  1179. (ID, alert_task_id,alert_task_seq,alert_type,
  1180. alert_color, alert_object_type,
  1181. alert_object_name, alert_message,alert_action)
  1182. VALUES
  1183. (0,task_id, task_seq, "INFO", "yellow", "DATABASE",
  1184. "Auto Update Statistics",
  1185. "Found "||trows||" table(s) in database ["||trim(aus_dbsname)|| "]"
  1186. || " which need statistics updated. ",
  1187. NULL);
  1188. ELSE
  1189. INSERT INTO ph_alert
  1190. (ID, alert_task_id,alert_task_seq,alert_type,
  1191. alert_color, alert_object_type,
  1192. alert_object_name, alert_message,alert_action)
  1193. VALUES
  1194. (0,task_id, task_seq, "INFO", "green", "DATABASE",
  1195. "Auto Update Statistics",
  1196. "Found "||trows||" table(s) in database ["||trim(aus_dbsname)|| "]"
  1197. || " which need statistics updated.",
  1198. NULL);
  1199. END IF
  1200. DROP INDEX aus_work_info_idx1;
  1201. DROP INDEX aus_work_info_idx2;
  1202. DROP INDEX aus_work_dist_idx1;
  1203. DROP INDEX aus_work_icols_idx1;
  1204. TRUNCATE TABLE aus_work_info;
  1205. TRUNCATE TABLE aus_work_dist;
  1206. TRUNCATE TABLE aus_work_icols;
  1207. END FOREACH --- End Database FOREACH
  1208. UPDATE aus_cmd_info
  1209. SET (aus_ci_etime) = ( aus_get_realtime())
  1210. WHERE aus_ci_database IS NULL;
  1211. LET errnum = aus_cleanup_table(1);
  1212. IF inHDRmode = 1 THEN
  1213. CREATE INDEX informix.aus_command_ix1 ON aus_command(aus_cmd_id) ONLINE;
  1214. CREATE INDEX informix.aus_command_ix2 ON aus_command( aus_cmd_state,
  1215. aus_cmd_priority DESC, aus_cmd_partnum, aus_cmd_type DESC)
  1216. ONLINE;
  1217. ELSE
  1218. CREATE INDEX informix.aus_command_ix1 ON aus_command(aus_cmd_id);
  1219. CREATE INDEX informix.aus_command_ix2 ON aus_command(aus_cmd_state,
  1220. aus_cmd_priority DESC, aus_cmd_partnum, aus_cmd_type DESC);
  1221. END IF
  1222. LET errnum = aus_rel_exclusive_access();
  1223. IF bitand(myflags,1) > 0 THEN
  1224. LET errnum = aus_enable_refresh();
  1225. END IF
  1226. RETURN nrows;
  1227. END FUNCTION;
  1228. {*********************************************************
  1229. *
  1230. * The following section create the task in the database
  1231. * scheduler used by the AUS feature
  1232. *
  1233. ********************************************************
  1234. *}
  1235. DELETE from ph_task WHERE tk_name = "Auto Update Statistics Evaluation";
  1236. INSERT INTO ph_task
  1237. (
  1238. tk_name,
  1239. tk_type,
  1240. tk_group,
  1241. tk_description,
  1242. tk_execute,
  1243. tk_start_time,
  1244. tk_stop_time,
  1245. tk_frequency,
  1246. tk_enable
  1247. )
  1248. VALUES
  1249. (
  1250. "Auto Update Statistics Evaluation",
  1251. "TASK",
  1252. "PERFORMANCE",
  1253. "To Evaluate which columns and tables should have the statistics and distributions refreshed.",
  1254. "aus_evaluate_stats",
  1255. DATETIME(01:00:00) HOUR TO SECOND,
  1256. DATETIME(01:10:00) HOUR TO SECOND,
  1257. INTERVAL ( 1 ) DAY TO DAY,
  1258. 't'
  1259. );
  1260. DELETE from ph_task WHERE tk_name = "Auto Update Statistics Refresh";
  1261. INSERT INTO ph_task
  1262. (
  1263. tk_name,
  1264. tk_type,
  1265. tk_group,
  1266. tk_description,
  1267. tk_execute,
  1268. tk_start_time,
  1269. tk_stop_time,
  1270. tk_frequency,
  1271. tk_monday,
  1272. tk_Tuesday,
  1273. tk_Wednesday,
  1274. tk_Thursday,
  1275. tk_Friday,
  1276. tk_sunday,
  1277. tk_saturday,
  1278. tk_enable
  1279. )
  1280. VALUES
  1281. (
  1282. "Auto Update Statistics Refresh",
  1283. "TASK",
  1284. "PERFORMANCE",
  1285. "Refreshes the statistics and distributions which were recommended by the evaluator.",
  1286. "aus_refresh_stats",
  1287. DATETIME(01:11:00) HOUR TO SECOND,
  1288. DATETIME(05:00:00) HOUR TO SECOND,
  1289. INTERVAL ( 1 ) DAY TO DAY,
  1290. 'f',
  1291. 'f',
  1292. 'f',
  1293. 'f',
  1294. 'f',
  1295. 't',
  1296. 't',
  1297. 't'
  1298. );
  1299. create function aus_evaluate_stats(task_id integer, seq_id integer)
  1300. returns integer
  1301. external name '(aus_evaluator)'
  1302. language C;
  1303. CREATE FUNCTION aus_evaluator_upgrade()
  1304. RETURNING INTEGER
  1305. UPDATE ph_task SET
  1306. (tk_execute) = ( "aus_evaluate_stats")
  1307. WHERE tk_name = 'Auto Update Statistics Evaluation';
  1308. RETURN 0;
  1309. END FUNCTION;
  1310. CREATE FUNCTION aus_evaluator_downgrade()
  1311. RETURNING INTEGER
  1312. UPDATE ph_task SET
  1313. (tk_execute) = ( "aus_evaluator")
  1314. WHERE tk_name = 'Auto Update Statistics Evaluation';
  1315. RETURN 0;
  1316. END FUNCTION;
  1317. create function informix.aus_refresh_stats(task_id integer, seq_id integer,
  1318. run_time integer default 0)
  1319. returns integer
  1320. external name '(aus_refresh)'
  1321. language C;
  1322. CREATE FUNCTION informix.aus_refresh_upgrade()
  1323. RETURNING INTEGER
  1324. UPDATE ph_task SET
  1325. ( tk_execute, tk_enable ) = ( "aus_refresh_stats", 't' )
  1326. WHERE tk_name = 'Auto Update Statistics Refresh';
  1327. UPDATE ph_task SET
  1328. ( tk_frequency ) = ( INTERVAL ( 1 ) DAY TO DAY )
  1329. WHERE tk_name = 'Auto Update Statistics Refresh'
  1330. AND tk_frequency < INTERVAL ( 1 ) DAY TO DAY;
  1331. RETURN 0;
  1332. END FUNCTION;
  1333. CREATE FUNCTION informix.aus_refresh_downgrade()
  1334. RETURNING INTEGER
  1335. UPDATE ph_task SET
  1336. ( tk_execute, tk_enable, tk_frequency ) =
  1337. ( "aus_refresh_stats_orig", 'f', INTERVAL ( 1 ) SECOND TO SECOND )
  1338. WHERE tk_name = 'Auto Update Statistics Refresh';
  1339. RETURN 0;
  1340. END FUNCTION;
  1341. {**************************************************************************
  1342. MARK THE ABOVE TASKS AS SYSTEM TASKS AND FOR PRIVATE THREAD
  1343. **************************************************************************}
  1344. UPDATE ph_task SET tk_attributes = BITOR(tk_attributes, 12)
  1345. WHERE tk_name
  1346. IN ('Auto Update Statistics Evaluation',
  1347. 'Auto Update Statistics Refresh');
  1348. {**************************************************************************
  1349. RECORD THE VERSION OF AUS INSTALLED
  1350. **************************************************************************}
  1351. DELETE FROM ph_version WHERE object = 'AUS' and type = 'version';
  1352. INSERT INTO ph_version(object,type,value) VALUES ( 'AUS','version', 23 );
  1353. CLOSE DATABASE;