Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

Sangam 2019 - The Latest Features

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Wird geladen in …3
×

Hier ansehen

1 von 241 Anzeige

Weitere Verwandte Inhalte

Diashows für Sie (20)

Ähnlich wie Sangam 2019 - The Latest Features (20)

Anzeige

Aktuellste (20)

Anzeige

Sangam 2019 - The Latest Features

  1. 1. 1 Connor McDonald bit.ly/techguysong
  2. 2. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | The latest and greatest
  3. 3. The latest and greatest Copyright © 2019 Oracle and/or its affiliates.
  4. 4. design.oracle.com
  5. 5. Copyright © 2019 Oracle and/or its affiliates.
  6. 6. 9 Me youtube bit.ly/youtube-connor blog connor-mcdonald.com twitter @connor_mc_d 400+ posts mainly on database & development 250 technical videos, new uploads every week rants and raves on tech and the world :-)
  7. 7. 10 etc... facebook bit.ly/facebook-connor linkedin bit.ly/linkedin-connor instagram bit.ly/instagram-connor slideshare bit.ly/slideshare-connor
  8. 8. 11 missed OpenWorld ? http://bit.ly/oow19mega
  9. 9. "latest and greatest" Copyright © 2019 Oracle and/or its affiliates.
  10. 10. 15 18c, 19c, 20c
  11. 11. The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation. Statements in this presentation relating to Oracle’s future plans, expectations, beliefs, intentions and prospects are “forward-looking statements” and are subject to material risks and uncertainties. A detailed discussion of these factors and other risks that affect our business is contained in Oracle’s Securities and Exchange Commission (SEC) filings, including our most recent reports on Form 10-K and Form 10-Q under the heading “Risk Factors.” These filings are available on the SEC’s website or on Oracle’s website at http://www.oracle.com/investor. All information in this presentation is current as of September 2019 and Oracle undertakes no duty to update any statement in light of new information or future events. Safe Harbor Copyright © 2019 Oracle and/or its affiliates.
  12. 12. 17 before we begin
  13. 13. 18 let's clear the air
  14. 14. 19 it's probably not about features
  15. 15. 21 upgrade
  16. 16. STOP
  17. 17. FREAKIN'
  18. 18. THE
  19. 19. HELL
  20. 20. OUT :-)
  21. 21. 27 18c 19c 20c 21c etc
  22. 22. 28 "Upgrade every single year !?!?!?!?!?!?"
  23. 23. 29 no
  24. 24. 30 customer needs/types
  25. 25. 31 W T H
  26. 26. 32 "I need security patches but other than that, leave me alone..."
  27. 27. 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 EXTENDED* 18c 11.2.0.4 EXTENDED EXTENDED12.1.0.2 12.2.0.1 19c Paid Extended SupportPremier Waived Extended Support Fee MOS Note 742060.1
  28. 28. • Premier Support to 2023 • Extended Support to 2026
  29. 29. 12.2.0.1 12.1.0.2 11.2.0.4 12.2.0.2 12.2.0.3
  30. 30. 36 check out autoupgrade https://mikedietrichde.com/2019/04/29/the-new-autoupgrade-utility-in- oracle-19c/
  31. 31. 37 W T H
  32. 32. 38 O M G
  33. 33. 39 "OMG! OMG! OMG! OMG! Competive edge! Fix to killer issue! Let's upgrade right now!"
  34. 34. 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 EXTENDED* 18c 11.2.0.4 EXTENDED EXTENDED12.1.0.2 12.2.0.1 19c 20c 21c 22c *Estimated Release
  35. 35. 41 database granularity
  36. 36. 42 11.2.0.4 => 12.1 => 12.1.0.2 => 12.2 11.2.0.4 => 12.2 => 19c
  37. 37. 44 this session
  38. 38. 45 preparing for when you get there
  39. 39. 46 there's a lot in 18, 19 .... and 20
  40. 40. 47 get started right now
  41. 41. 48 install nothing
  42. 42. https://cloud.oracle.com/tryit
  43. 43. 50 install a little bit
  44. 44. https://bit.ly/oraprebuilt
  45. 45. 52 install lots :-)
  46. 46. http://bit.ly/download19c
  47. 47. 54 18c/19c install lots :-)
  48. 48. 56 18c/19c install lots :-)
  49. 49. 59 install lots :-)
  50. 50. 61 1) read-only ORACLE_HOME
  51. 51. 62 2) database in Docker
  52. 52. UNZIP INSTALL RPM INSTALL DOCKER READ-ONLY
  53. 53. 65 vmware
  54. 54. 68 Doc ID 249212.1
  55. 55. run, lift & shift, license
  56. 56. 71 global temporary tablesprivate
  57. 57. 72 SQL server etc
  58. 58. 73 read locking
  59. 59. 74 SELECT empno, ename, job INTO #HighPaidJobs FROM emp WHERE sal > 3000
  60. 60. 75 migration to Oracle difficult
  61. 61. SQL> create private temporary table ORA$PTT_MY_TT 2 ( empno int , ename varchar2(20)) ; Table created. SQL> insert into ORA$PTT_MY_TT 2 select empno, ename 3 from scott.emp 4 where sal > 3000; 1 row created. SQL> select * from ORA$PTT_MY_TT; EMPNO ENAME ---------- -------------------- 7839 KING
  62. 62. 77 "um...looks the same as before"
  63. 63. 78 SQL> commit; Commit complete. SQL> select * from ORA$PTT_MY_TT; select * from ORA$PTT_MY_TT * ERROR at line 1: ORA-00942: table or view does not exist
  64. 64. 79 it's really temporary
  65. 65. SQL> create private temporary table ORA$PTT_MY_TT 2 ( empno int , ename varchar2(20)) ; Table created. SQL> select * 2 from user_tables 3 where table_name = 'ORA$PTT_MY_TT' ; no rows selected SQL> select * 2 from all_objects 3 where object_name = 'ORA$PTT_MY_TT' ; no rows selected
  66. 66. 82 it's really private
  67. 67. 83 SQL> create private temporary table ORA$PTT_MY_TT 2 ( empno int , 3 ename varchar2(20)) ; Table created. SQL> create private temporary table ORA$PTT_MY_TT 2 ( deptno int , 3 dname varchar2(20), 4 bonus int, 5 logo blob) ; Table created.
  68. 68. 84 it's all in the name !
  69. 69. SQL> create private temporary table MY_TT ( x int ) ; ERROR at line 1: ORA-00903: invalid table name SQL> show parameter private NAME TYPE VALUE ------------------------------- ----------- ----------- private_temp_table_prefix string ORA$PTT_
  70. 70. 87 remember temporary undo?
  71. 71. SQL> insert into t values ('Hello','There'); insert into t values ('Hello','There') * ERROR at line 1: ORA-16000: database open for read-only access
  72. 72. 89 Active Data Guard
  73. 73. SQL> alter session set temp_undo_enabled=true; Session altered. SQL> create global temporary table GTT_REPORT_STAGING 2 ( ... ); SQL> insert into GTT_REPORT_STAGING 2 select ... SQL> select * from GTT_REPORT_STAGING join FIN_RESULTS 2 ...
  74. 74. 91 100% % of people that found this useful
  75. 75. 92 19c
  76. 76. 93 DML redirect
  77. 77. Standby Primary SQL> insert into REPORTING_STAGING 2 select * from ...
  78. 78. 95 bonus DataGuard
  79. 79. 96 we've all done this :-)
  80. 80. 97 Standby Primary
  81. 81. 98 18c
  82. 82. RMAN> connect target sys/oracle@MY_STANDBY RMAN> connect auxiliary sys/oracle@MY_PRIMARY RMAN> recover database from service PRIMARY; Starting recover at 12.10.2018 14:05:17 using target database control file instead of recovery catalog allocated channel: ORA_DISK_1 channel ORA_DISK_1: SID=187 device type=DISK ... ...
  83. 83. 100 bonus bonus DataGuard !
  84. 84. 101 SQL> alter database force logging;
  85. 85. 103 18c
  86. 86. 104 SQL> alter database set standby nologging for data availability; deferred commit
  87. 87. 105 SQL> alter database set standby nologging for load performance; deferred transmission
  88. 88. 107 a nice form of murder :-)
  89. 89. 108 aka, #1 reason for upgrading to 18c
  90. 90. 109 SQL> insert into MY_TABLE 2 select * 3 from MY_HUGE_GREAT_FAT_TABLE;
  91. 91. 111 SQL> insert into MY_TABLE 2 select * 3 from MY_HUGE_GREAT_FAT_TABLE 4 where LOAD_DATE > sysdate - 1;
  92. 92. 112 SQL> alter system kill session '123,456' immediate
  93. 93. 114 18c
  94. 94. 115 SQL> alter system cancel sql '123,456';
  95. 95. 117 speaking of "#1 reason"
  96. 96. 118 #1 reason for upgrading to 19c developers
  97. 97. 119 SQL> select deptno, ename 2 from emp 3 order by 1,2; DEPTNO ENAME ---------- ---------- 10 CLARK 10 KING 10 MILLER 20 ADAMS 20 FORD 20 JONES 20 SCOTT 20 SMITH 30 ALLEN 30 BLAKE 30 JAMES 30 MARTIN 30 TURNER 30 WARD
  98. 98. 120 DEPTNO MEMBERS ---------- ------------------------------------- 10 CLARK,KING,MILLER 20 SMITH,JONES,SCOTT,ADAMS,FORD 30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES
  99. 99. 121 how we used to do it
  100. 100. SQL> select deptno , rtrim(ename,',') enames 2 from ( select deptno,ename,rn 3 from emp 4 model 5 partition by (deptno) 6 dimension by ( 7 row_number() over 8 (partition by deptno order by ename) rn 9 ) 10 measures (cast(ename as varchar2(40)) ename) 11 rules 12 ( ename[any] 13 order by rn desc = ename[cv()]||','||ename[cv()+1]) 14 ) 15 where rn = 1 16 order by deptno; DEPTNO ENAMES ---------- ---------------------------------------- 10 CLARK,KING,MILLER 20 ADAMS,FORD,JONES,SCOTT,SMITH 30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
  101. 101. SQL> select deptno, 2 substr(max(sys_connect_by_path(ename, ',')), 2) members 3 from (select deptno, ename, 4 row_number () 5 over (partition by deptno order by empno) rn 6 from emp) 7 start with rn = 1 8 connect by prior rn = rn - 1 9 and prior deptno = deptno 10 group by deptno 11 / DEPTNO MEMBERS ---------- --------------------------------------------------------- 30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES 20 SMITH,JONES,SCOTT,ADAMS,FORD 10 CLARK,KING,MILLER
  102. 102. SQL> select deptno, 2 xmltransform 3 ( sys_xmlagg 4 ( sys_xmlgen(ename) 5 ), 6 xmltype 7 ( 8 '<?xml version="1.0"?><xsl:stylesheet version="1.0" 9 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 10 <xsl:template match="/"> 11 <xsl:for-each select="/ROWSET/ENAME"> 12 <xsl:value-of select="text()"/>,</xsl:for-each> 13 </xsl:template> 14 </xsl:stylesheet>' 15 ) 16 ).getstringval() members 17 from emp 18 group by deptno; DEPTNO MEMBERS ---------- -------------------------------------------------------- 10 CLARK,MILLER,KING, 20 SMITH,FORD,ADAMS,SCOTT,JONES, 30 ALLEN,JAMES,TURNER,BLAKE,MARTIN,WARD,
  103. 103. SQL> create or replace type string_agg_type as object 2 ( 3 total varchar2(4000), 4 5 static function 6 ODCIAggregateInitialize(sctx IN OUT string_agg_type ) 7 return number, 8 9 member function 10 ODCIAggregateIterate(self IN OUT string_agg_type , 11 value IN varchar2 ) 12 return number, 13 14 member function 15 ODCIAggregateTerminate(self IN string_agg_type, 16 returnValue OUT varchar2, 17 flags IN number) 18 return number, 19 20 member function 21 ODCIAggregateMerge(self IN OUT string_agg_type, 22 ctx2 IN string_agg_type) 23 return number 24 ); 25 /
  104. 104. 126 11g
  105. 105. 127 SQL> select deptno, 2 listagg( ename, ',') 3 within group (order by empno) members 4 from emp 5 group by deptno; DEPTNO MEMBERS ---------- ----------------------------------------- 10 CLARK,KING,MILLER 20 SMITH,JONES,SCOTT,ADAMS,FORD 30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES
  106. 106. 128 except
  107. 107. SQL> select deptno 2 listagg(job,',') within group ( order by job) as jobs 3 from scott.emp 4 group by deptno 5 order by 1; DEPTNO JOBS --------- -------------------------------------------------- 10 CLERK,MANAGER,PRESIDENT 20 ANALYST,ANALYST,CLERK,CLERK,MANAGER 30 CLERK,MANAGER,SALESMAN,SALESMAN,SALESMAN,SALESMAN
  108. 108. 131 19c
  109. 109. SQL> select deptno 2 listagg(distinct job,',') within group ( order by job) as jobs 3 from scott.emp 4 group by deptno 5 order by 1; DEPTNO JOBS --------- -------------------------------------------------- 10 CLERK,MANAGER,PRESIDENT 20 ANALYST,CLERK,MANAGER 30 CLERK,MANAGER,SALESMAN
  110. 110. 133 since we're talking SQL
  111. 111. 135 20c
  112. 112. 136 SQL macros
  113. 113. 137 encapsulation of SQL logic
  114. 114. 138 scalar and table level encapsulation
  115. 115. 139 example: scalar
  116. 116. 140 numeric TRIM if x < lower return lower if x > upper return upper otherwise return x
  117. 117. SQL> create function clip 2 (lo number, x number, hi number) 3 return number is 4 begin 5 return least(greatest(x, lo), hi); 6 end; 7 /
  118. 118. SQL> create function clip 2 (lo number, x number, hi number) 3 return varchar2 SQL_MACRO(SCALAR) is 4 begin 5 return 'least(greatest(x, lo), hi)'; 6 end; 7 /
  119. 119. 143 not a PL/SQL function call
  120. 120. SQL> select 2 empno, 3 sal, 4 clip(sal, 1000, 2000) clipped 5 from scott.emp; EMPNO SAL CLIPPED ---------- ---------- ---------- 7369 800 1000 7499 1600 1600 7521 1250 1250 7566 2975 2000 ... SELECT ename, least(greatest(sal, :lower), :upper) FROM emp;
  121. 121. 145 cross database migration
  122. 122. SQL> create function strpos 2 (str varchar2, sub_str varchar2) 3 return varchar2 SQLMACRO(SCALAR) 4 is 5 begin 6 return 'instr(str, sub_str)'; 7 end; 8 /
  123. 123. 147 example: table
  124. 124. SQL> CREATE FUNCTION budget(dept_no number) 2 RETURN varchar2 SQL_MACRO(TABLE) IS BEGIN 3 RETURN q'[ 4 SELECT 5 d.deptno, 6 SUM(e.sal) budget, 7 count(e.empno) headcount, 8 count(e.mgr) mgr_headcount 9 FROM emp e, dept d 10 WHERE d.deptno = :dept_no 11 AND e.deptno = d.deptno 12 GROUP BY d.deptno]'; 13 end;
  125. 125. SQL> WITH east_coast as 2 (SELECT deptno 3 FROM dept 4 WHERE loc = 'Boston' 5 ) 6 SELECT * 7 FROM budget(east_coast);
  126. 126. 150 polymorphic table macro select * from NJ( sales, products, customers); select * from sales natural join products natural join customers
  127. 127. 151 cool but scary :-)
  128. 128. 153 back to #1 reason for upgrading to 19c DBAs
  129. 129. 154 back to bad SQL
  130. 130. 155 maybe cancelling the SQL won't help
  131. 131. BAD SQL
  132. 132. 157 bad SQL just keeps coming back...
  133. 133. 158 19c
  134. 134. 160 quarantine of bad SQL elapsed time resource consumption
  135. 135. 161 error on subsequent execution
  136. 136. 162 manually
  137. 137. SQL> set feedback on sql_id SQL> select count(*) from scott.emp, scott.emp, scott.emp, 2 ( select 1 from dual connect by level <= 100000 ); COUNT(*) ---------- 274400000 1 row selected. SQL_ID: dcrqdagwxagth
  138. 138. SQL> declare 2 q varchar2(30); 3 begin 4 q := dbms_sqlq.create_quarantine_by_sql_id( 5 sql_id => 'dcrqdagwxagth'); 6 end; 7 / PL/SQL procedure successfully completed. SQL> select count(*) from scott.emp, scott.emp, scott.emp, 2 ( select 1 from dual connect by level <= 100000 ); * ERROR at line 1: ORA-56955: quarantined plan used
  139. 139. 165 automatic via resource manager
  140. 140. .... 21 22 dbms_resource_manager.create_plan_directive( 23 PLAN=> 'EXEC_TIME_LIMIT', 24 GROUP_OR_SUBPLAN=>'CG_EXEC_TIME_LIMIT_CANCEL', 25 COMMENT=>'Kill statement after exceeding total time', 36 SWITCH_GROUP=>'CANCEL_SQL', 37 SWITCH_TIME=>10, 38 SWITCH_ESTIMATE=>false, 39 SWITCH_FOR_CALL=> TRUE 40 ); .... 46 end; 47 / PL/SQL procedure successfully completed.
  141. 141. SQL> select count(*) from emp, emp, emp, 2 ( select 1 from dual connect by level <= 50000 ); COUNT(*) ---------- 27440000 Elapsed: 00:00:04.11 SQL> select count(*) from emp, emp, emp, 2 ( select 1 from dual connect by level <= 1000000 ); ERROR at line 1: ORA-00040: active time limit exceeded - call aborted Elapsed: 00:00:12.00
  142. 142. SQL> select count(*) from scott.emp, scott.emp, scott.emp, 2 ( select 1 from dual connect by level <= 100000 ); * ERROR at line 1: ORA-56955: quarantined plan used
  143. 143. SQL> desc V$SQL Name Null? Type ---------------------- -------- ---------------------------- SQL_TEXT VARCHAR2(1000) SQL_FULLTEXT CLOB ... ... SQL_QUARANTINE VARCHAR2(128) AVOIDED_EXECUTIONS NUMBER
  144. 144. 172 future
  145. 145. 173 automated diagnosis/repair
  146. 146. 175 "remember" multitenant ?
  147. 147. cool
  148. 148. cloninghotcloninghot
  149. 149. SQL> CREATE PLUGGABLE DATABASE prod_copy FROM prod 2 FILE_NAME_CONVERT=('/u01/oradata/cdb/prod', 3 '/u01/oradata/cdb/prod_copy'); Pluggable database created. SQL> ALTER PLUGGABLE DATABASE prod_copy OPEN;
  150. 150. 186 refresh
  151. 151. SQL> conn / as sysdba Connected. SQL> alter pluggable database pdb_ro refresh Table created.
  152. 152. Server1 CDB1 CDB2 Server2 create pluggable database Grey from Grey@CDB2_Link refresh mode auto every 2 minutes; create pluggable database Red from Red@CDB1_Link refresh mode auto every 2 minutes;
  153. 153. 194 so ........ much ......... goodness
  154. 154. 195 no-one uses it
  155. 155. 197 IMPORTANT
  156. 156. 198 multi-tenant
  157. 157. 199 20c onwards ... non-cdb desupported
  158. 158. 200 20c onwards ... only multitenant
  159. 159. 201
  160. 160. 202 19c onwards ... 3 pluggable databases WITH NO MULTITENANT LICENSE
  161. 161. 203 do it now ! not at upgrade
  162. 162. 205 back to our slow running SQL
  163. 163. cool
  164. 164. 207 maybe the SQL is fine...
  165. 165. 208 SQL> insert into MY_TABLE 2 select * 3 from MY_HUGE_GREAT_FAT_TABLE 4 where LOAD_DATE > sysdate - 1/24;
  166. 166. 209 SQL> insert into MY_TABLE 2 select * 3 from MY_HUGE_GREAT_FAT_TABLE 4 where LOAD_DATE > sysdate - 1/24; need an index?
  167. 167. 210 what are REALLY do ...
  168. 168. 212 SQL> create index LET_ME_GET_BACK_TO_SLEEP 2 on MY_PROBLEM_TABLE ( 3 SOME_COLUMNS );
  169. 169. 214 what are MEANT to do ...
  170. 170. 215 1) extract candidate SQL statements 2) consider candidate indexes per SQL 3) consolidate overlaps 4) create invisible/unusable 5) check "virtual" explain plan
  171. 171. 216 6) create true index (as invisible) 7) test execute each SQL for benefit 8) decide on index benefit for each SQL 9) SPM to avoid regressions 10) make new indexes visible
  172. 172. 217 every 15 minutes
  173. 173. 219 19c automatic indexes
  174. 174. 220 follows the best practice
  175. 175. 225 very cool ...
  176. 176. 226 ... much more to be done FK locking compression coalesce IOT etc
  177. 177. 228 statistics
  178. 178. 229 what most of us do
  179. 179. Gather Stale overnight
  180. 180. 231 19c
  181. 181. Conventional DML Real-time Statistics Gathered Statistics Lightweight Statistics
  182. 182. 233 real time statistics DML driven
  183. 183. 234 only "cheap" essential statistics high/low values row/column counts
  184. 184. 235 lightweight rapid gather resource manager
  185. 185. THIS
  186. 186. IS
  187. 187. THE
  188. 188. BIG
  189. 189. ONE
  190. 190. 242 18c XE
  191. 191. 243 100% free
  192. 192. 244 We grant you a nonexclusive, nontransferable limited license to use the programs for: (a) purposes of developing, prototyping and running your applications for your own internal data processing operations; (b) you may also distribute the programs with your applications; (c) you may use the programs to provide third party demonstrations and training; and d) you may copy and distribute the programs to your licensees provided that each such licensee agrees to the terms of this Agreement https://www.oracle.com/technetwork/licenses/db18c-express-license-5137264.html
  193. 193. 245 12 GB of user data 2 GB of database RAM 2 CPU threads 3 Pluggable Databases
  194. 194. 246 "Is it feature hobbled?"
  195. 195. Oracle Multitenant SQLJ Online index rebuild Online table reorg Online table redefinition Trial recovery Fast start recovery Flashback table Flashback query Flashback database Advanced Queueing Network Compression Client side result cache Server side result cache Adaptive plans In-memory column store In-memory aggregation Attribute Clustering Column encryption Tablespace encryption Advanced Security Database Vault Label Security AD users Privilege Analysis Real Application Security Data Redaction Virtual Private Database Spatial Graph Partitioning Advanced Analytics Advanced Compression Advanced Index Compression Transportable Tablespace Query Rewrite
  196. 196. 248 EE plus most extra cost options
  197. 197. 250 free multitenant + free XE
  198. 198. 251
  199. 199. 252 I lied .....
  200. 200. THIS
  201. 201. IS
  202. 202. THE
  203. 203. ONE
  204. 204. oracle.com/gbtour New Free Tier Always Free Oracle Cloud Infrastructure Services you can use for unlimited time 30-Day Free Trial Free credits you can use for more services +
  205. 205. Autonomous Database 2 x Databases 20GB Storage Each Load Balancing 10 Mbps Bandwidth Shape Storage 2 x 50GB Block 10GB Object 10GB Archive Compute 2 x VM 1GB Memory Each
  206. 206. FREE FOREVER
  207. 207. https://dgielis.blogspot.com/2019/09/best-and-cheapest-oracle-apex-hosting.html
  208. 208. 262 wrap up
  209. 209. 263 18c, 19c, 20c, ......
  210. 210. 264 satisfying both customer types
  211. 211. 265 lots not covered today
  212. 212. 266 you can check it out all for free
  213. 213. 267 Thanks for coming ! youtube bit.ly/youtube-connor blog connor-mcdonald.com twitter @connor_mc_d

×