Cool New Features for Developers in Oracle Database 18c and Oracle Database 12c

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay right so for the people who just came in very briefly my name's Tim I'm from the UK been working with Oracle tech for over 23 years been doing a website for over 18 years and if you have come across it when you've googled that's me it's what I do in my spare time because I have no life I leave work I turn on a computer and I start playing with Oracle and writing about it as a result of all these years of playing with Oracle and putting stuff on the internet I got invited to the ACE program twelve years ago and as a result of that got to go around the world talking about tech so I'm very grateful but that's enough about me what are we going to talk about today I want to talk about some features in the Oracle database that have appeared in 12 one twelve two and eighteen see that I think pretty cool therefore cool for different reasons some are cool because they're geeky some are cool because they're really useful I don't know how many we'll get to cover today but I will point you at a links page for all of this so you can try to match your heart's content this is mostly going to be demos so if you struggle to see the screen move forward fall asleep leave whichever works for you okay so let's jump in so Oracle have been on a bit of a journey where JSON support is concerned since Oracle 12c release one we've been able to do stuff in the database with Jason for a long time thanks to people like Mike and his folks who gave us the Apex Jason package which is still really cool but now what we're getting with every release is more functionality directly in the database in 12-1 I feel like most of the emphasis was on consuming Jason so I've got Jason coming into the database what do I do with it and we have things like the is Jason Jason exists and Jason contains conditions that allow us to look at stuff in Jason and maybe search through that a little bit if we've got if we're talking about actually interrogating the contents of the Jason then we've got Jason value Jason query Jason table that allow us to actually interrogate the contents of the Jason information in a variable or in a table and pull out relational type data we also got a thing that really want to talk too much about today called soda and that works in conjunction with the 12c database and odds to allow Oracle rest data services to allow you to use the database as a document store a JSON document store so if you've got a big investment in Oracle anyway and you want to use a document store that's a pretty good combination in 12 - we got something that in my head is more about producing Jason from the database there's also some additional things for consumption of Jason so we got SQL Jason so has anyone used SQL XML - yeah okay so to produce XML directly from a query well we've kind of got that nap but we have got that now from 12:00 to 1:00 words built into the database and I'll show you an example of that all of the stuff that appeared in 12-1 is natively supported in 12 - in pl/sql we also got some new object types so if we want now we can use apex Jason Steele or we can use the native types in the database to either produce or pass JSON information and we've got this really cool thing called the JSON data guide which I want to start off with because I think it really epitomizes to me what we get out of our call that makes our life easy and allows me to do things without understanding a thing okay which is always good for me so let's have a look at and oh I suppose I should have shown you the slide first even though all it tells me to do is run the demo so JSON data guide what I'm going to do is create a really basic table it's just got an ID with the primary key and a club in it Oracle doesn't have a specific data type for Jason I can use a voucher to a club a blob an N club whatever I want the important thing in terms of some of the functionality is that I include this check constraint it's not mandatory but I think it's pretty sensible so what I've got then is my my JSON data is going to go in this column called data and I've got a constraint that says check data column is Jason so now I can only insert validation into that otherwise I get an error out of it I'm going to insert some JSON into that single row at the moment just using a Cisco Eid for the primary key but that could be a sequence or I could use an identity column for that and I've got some JSON and notice it's got some structure it's not just key value pairs in the conventional sense because I've got a JSON object to represent the address and a JSON object to represent the contact details notice this one has got a Twitter handle but the next row I insert doesn't what's gone off-screen the contact details doesn't have to have a Twitter handle it's not important but we'll get onto that notice also the phone number the elements are present but has no value it's a null so I gather some stats for the hell of it and then I create this thing called adjacent search index so just looks like a normal Jason so your normal index creation but notice this for jason we could create jason search indexes in 12:1 but it had a bit of a funky syntax and it didn't have this extra bit of functionality in it but in 12 - the syntax is simplified and by doing this by default we get something called a JSON data guide I can actually look at what this data guide contains by using well there's couple of methods in this case I'm going to use DBMS Jason package get index data guide specify the table name the column and the format of how I want this to look and what I can see is the what Oracle's done by creating that Jason search index is it's gathered a bunch of information about the contents of that column so I can see that it's gone and looked at what elements are stored in that column and the structures of it the size of the elements things like that okay now if I gather stats again I actually get some more information added to that because it can put statistical information so I just check the data guide again and we can see that it's got more information in now including high and low values and also frequency so I can see as I expected only 50% of the rows stored in this I've got a Twitter handle not that that matters but we can use that for some of the functionality later so what Oracle's gone and done is looked at the contents of the JSON documents stored in that column because it's got a JSON search index and it's given me back some information I can also look at that information in a different way that's probably a bit easier to read in 12-2 I can use JSON table to project some column volume values over the JSON data and actually pull out the path the type and the length of that data and I can see that Oracle has noticed these elements are in the data and these are the types and the lengths of it if I'm on a teensy I have an even easier way of doing this because there's a new view called user JSON data guide fields and once again just by creating that JSON search index without me understanding what Jason even is I've got information about what's in there so that's great I've got all that so what who cares well this is where it gets kind of good in my opinion I've got this table called JSON documents with that JSON data in it what I can do now is say call DBMS Jason add virtual columns specified the table named the column name and tell it what the data guide is and what it will do now is add virtual columns to my table so now I can interact with the contents of the Jason without understanding what Jason is because it just looks like a regular table I can't insert they're just virtual columns read-only but I don't have to worry about programming I don't have to worry about passing the data Oracle's done that for me you'll see the name is the column name a dollar sign and then the element name which is a little bit ugly but I can sort that I'll get rid of those columns so I'm back to the basic table again and that's gone off screen what you can see here is me just associating new names with all the columns so I'm saying a mapping between the element name and a name I want to give it which I'm calling it DG job for job because data guide not data guard okay so now if I create those virtual columns again you can see that they have nicer names because the other ones were a bit ugly so I'm able now to interact with those columns just like regular columns I mean virtual columns is a feature in the database I can do select of the original ID and then some of these things and in the background Oracle is actually interrogating that JSON data for me I don't have to program anything you might be saying to yourself I don't really want to start tampering with my table structure that's kind of going to confuse people well that's all good we can get rid of those I'm going to change the names to something even simpler so now rather than DG underscore I've just got the word that represents the elements so job active City address line 1 that sort of stuff and what I can do if I can get yes what I can do is a DBMS job dot create view passing a view name that I want the table name the column the data guide and what Oracle will do is create a view of the primary key column or columns and then all of those elements that's in the data I can actually do something kind of funky as well which I can set some parameters to say if any new data comes in that produces new elements kind of add those as well which i think is kind of dangerous but you know you can do this sort of thing with the virtual columns as well so I just think this is a really neat way of getting the data out of the database without having to worry about programming letting Oracle do the hard work and not surprisingly I can query that view now as if it were a regular view and not have to understand anything about Jason so we go from hey I've got a bunch of data in the database and I really don't know anything about Jason the apex Jason package or the built-in data types and I don't want to have to learn how to use something like Jason query or Jason table you don't have to learn anything you've got that data straight away so I think that's pretty cool and it's a value add from the database you know if you want to program that manually go nuts it's no problem hello yes so yet that will just that's fine that all just flattens it out sure so that was Jason data guide which i think is a really neat feature I just want to briefly touch on the SQL JSON functionality that appeared in 12 - so this is about producing Jason directly from a query so I've just built the amp table because as everyone knows it is the only table you'll ever need and what I'm going to do first of all is just use JSON object so with JSON object we have key value pairs comma separated and it's literally just going to turn whatever I put in there into a JSON object in case you don't know a JSON object is a one or more comma separated key value pairs and it's surrounded by curly braces okay so you can have complex or simple objects displayed that way I've got four tables in oh this is actually Department so you need two tables not just one this is four rows in the department's table and I've turned each of those rows essentially into JSON we have JSON object AG which takes a key value pair and then it aggregates all the instances of that data into an object again so in this case I've said my key is the department name and the value is the department number and that's what I get okay I've got JSON array which not surprisingly turns a comma separated list of stuff in this case typically key value pairs or or even objects into a JSON array now a JSON array is a comma separated list of stuff surrounded by square brackets I've also got jason array ag and this takes once again a value and it gets that radiation array and i can order the contents of that so all of these look incredibly simple and individually individually a little bit useless but when we combine them together then we can do some quite funky stuff so we imagine a situation where i want to create a list of departments with each departments having a list of employees in it well I can do a JSON object the key of departments in a value of an array an array of departments so that's a object called department with a value of this object made up of department name department number and employees but the value of employees is Jason array AG which in turn is aggregating adjacent object made up of the employees so in one statement I've got that nested structure being produced and it's going to look like that which is a bit ugly because of course we minify it to make sure it doesn't waste lots of space but if I were to beautify that you would see a list kind of like this which is a list of departments with their employees under it all coming from a single SQL statement I'm totally happy with you doing that programmatically but I don't have to okay so I think if you've used SQL XML before this will feel very natural if you've not it will feel weird at first but then it's really easy to start producing Jason to get it out of your database it's not the only way there are many ways but this is pretty handy the other thing I want to mention I'm not going to demo this because I'd have to show you a lot of code is these new objects that were introduced in 12:2 so by all means carry on using Apex Jason if that's the way you want to go but there are new objects now to natively allow you to pass and create Jason programmatically and essentially this is just the same way you'd process something using any procedural tool so in this case I'm passing in a club I'm turning it to a JSON object I'm getting an array of departments I'm looping through them for each department I'm going to get the department data and then I'm going to get the array of employees loop through that and pull out that information so just the same way you would with any sort of procedural language really so that's all there out of the box if you're on 12 - or higher the next thing I want to talk about is real-time materialized views so completely different to the last one we often use materialized views to try and summarize information maybe you've got a dashboard in your application that you want to frequently update and you've got some queries that do lots and lots of aggregation and it's kind of painful to run those repeatedly to populate many people's dashboards so you do all the work once in a materialized view or a group of materialized views and that's all good but the problem is the data is constantly changing and the materialized views are becoming stale and then you either have to accept the fact that you're using stale data or refresh like crazy hoping that the dashboards stay current or even worse go back to the base tables to get the up-to-date data well real-time materialized views go a long way to solving that problem for you so let's have a look at a demo and now this demo I'm going to have to shoot through some sections a bit quick otherwise the information drops off and I can't give you the execution plans so bear with me I will try and jump back so I'm creating a table called order lines it's not really important what's in it but notice it's got an ID order ID line quantity total value and I'm going to populate that with 100,000 rows of random data so I'm just using DBMS random to put anything in there so I don't know what's in there other than it's a hundred thousand rows gathered some stats I will create a materialized view log so I dropped it but it wasn't there create a materialized view log on that table so that I can do a fast refresh of a materialized view and then I'm going to create a materialized view to all intents and purposes this is just like any other materialized view notice I'm doing aggregation some sums of the line quantity total value in account so adding a little of extra work to it but look at that line there enable on query computation so this tells Oracle something I want it to potentially do something for me and we'll see what that is in a moment so if I query the base table so notice I'm not querying a materialized view I'm querying the base table I get 107 rows Act four order ID one if I look at the execution plan what I can see is I've actually accessed the materialized view not the base table this is normal in Oracle for quite some time if I recall optimizer can see that there's a better way of getting that data than running it against the base tables it's going to do that and at this point this is totally safe to do this because the materialized view has all of that information in in a much more concise form than going and doing the work from the base table so happy days I've just saved myself a whole bunch of work by being rewritten to the materialized view even though I've accessed the base table so now oh dear I've got another row added in to order lie order ID one so now what I can see is the materialized view is stale I've got staleness of needs compile that's the out on query computation flag so remember when I ran that query against the base table before I got 107 rows so I'm now expecting 108 rows but the materialized view is stale oh I've got 108 rows by querying the base table again if I have a look at the execution plan am i using the raw data or am i using the materialized view I'm actually using the materialized view but what's happened is just for my session oracle has actually looked at the MIPS has looked at the materialized view logs and it's wound forward the data in the material view to make it current this is only for my session and only for my statement so it hasn't done a refresh of the materialized view lot view it's still stale but it's given me up-to-date data so if I've constantly you've got a churn of data I haven't got to necessarily go to the expense of pulling the whole thing forward I can do it dynamically for my session and get current information it's clearly doing a lot more work to get that than a full table scan but it's potentially a lot better than me going back and hitting the base tables and doing all that work again so prior to this feature I had a choice of going back to the base tables and getting the raw data and working on it or accepting stale data now now I have another option which is to get up-to-date data without having to refresh my materialized view like crazy it's taking the materialized view it's taking the materialized view logs and it's manually winding it forward yeah so not dissimilar to doing a full refresh but because it's all done in memory it's a lot quicker than having to insert rows into the materialized views segment okay if I want to access the materialized view directly I can but notice it because it's stale I get the wrong data I get what's in the materialized view but what I can do is I can tell Oracle that actually I'd like it to wind this forward and I can add a hint in there which is oh sorry I should have said that's the execution plan for hitting the materialized view directly notice just a full table scan and it gave me the stale information but what I can do is say fresh MV hint and what it will do is even though I'm now accessing the materialized view directly it will still wind it forward and we'll get that rather ugly execution plan again where it's hitting the materialized view segment and winding it forward with the materialized view logs so if you can afford to refresh the whole materialized view a lot that's fine do that but if you're in a position where you've got a dashboard that's constantly in flight you may well find this allows you to keep using the materialized view but keep your dashboard up-to-date and not have to refresh it every like two seconds or something so I kind of feel that's a pretty cool feature because it's something that I've had to do the horrible way plenty of times in my career okay the next feature I think is pretty cool and this has been around for quite some time is top end queries so if you were to look at my websites I've got a bunch of stuff where I talk about top end queries but in 12-1 we got a much neater solution for this whoops if anyone's used something like MySQL before you'll know that top end queries are really easy because you've got the limit clause in MySQL so you can write a query with an order by and say limit the amount of rows coming back and you get your top end query it's really easy it wasn't that hard in Oracle but it was a little bit painful before so I've created a table I'm using a multi table insert to populate it so I've got the numbers 1 to 10 coming out of this query here and I'm inserting each number twice into the table so what I end up with is 20 rows two of each number in there that's going to be my data I'm going to use for my example so the old way we would do this is maybe this so select my value from the table order by the value descending so I'm going biggest to smallest and have that in an inline view or maybe in a with Clause and then select from that and limit my rows with Ronin so I've ordered the set and limited the rows and whoops and I get the value out what we can do from 12 1 onwards is to do my ordered query in a normal way and just do fetch first five rows only we also have some variations on that like say fetch first 20% of rows only okay so a much nicer solution much neater than having nested queries we also have another option which is to say hey fetch the first five rows with ties because if you remember we had two of each number so number five was actually the fifth position in the descending list was actually number eight and there were two of those so I can pull back with ties if I want I've already mentioned give me the first 20 percent of rows we can also page through data so back in the day what we had to do to achieve this was have my ordered Select pull back all the rows from the start up until the end of the last page I want to display and then throw away all of the rows that were there until the start of the last page I want to display so I've got this I've thrown away that and then I've thrown away that to get to my page it works it's fine it's just kind of ugly but what we can do with this new syntax is to say select value from a table order by in this case my value offset for rows next four rows only so I've offset to throw away the page pages before and then I have how many rows I want to show so this is a really simple way of paging through data the interesting thing about that though is it's just syntax candy because what happens is if you actually do the trace of that and look what's happening under the hood Oracle is rewriting that into the same type of query that you saw me write longhand or in some cases it's using analytic functions to do that behind the scenes so it's just making my life easier as a developer but under the hood it's doing the same thing it always did there's a question oh okay okay yeah there's no magic here you know so it is just syntax candy but I'll take that anything that makes my life easier you know a direct assignment to a variable of a sequence rather than having to lect into yeah it's the same thing the same things happening under the hood but anything that makes my job as a developer and makes my code look neater I'm really happy with qualified expressions I'm going to explain this really badly okay so if we think about life prior to eighteen see if I had an array structs are a record structure and I wanted to populate it I essentially had to populate each individual item I could do it maybe with a select in two or something but what we can do from 18 C onwards is we can treat the record structure almost like an object constructor so we can actually create a new instance of the record in one go that can either be positional so notice this looks almost like I'm pretending it's an object constructor the first time I saw this I thought you've always been able to do that in pl/sql since 8i but you really can't and it's because it looks so much like the object relational functionality that it fools you into thinking it's possible I can also do this in a position a notation way or named associations so I can actually only put in a few or I can alter the order of them just like I would with name notation when I call a procedure the important thing about this is that this is a new instance of that record so in imagine a situation where I only do say ID and Val - Val 1 is assigned null if I then want to reassign a new value and I say Val 2 isn't present then Val 2 is null if you think about what you currently have to do with record structures is every time you loop through you have to blank every element to make sure you've got no bleed through between loops this is a new instance of the record so there's no possibility of bleed through of data between loops so it's pretty handy it's even hand.you when we're talking about associative arrays or index by tables so back in the day we had to assign each of the values individually and then the next time through the loop if I wanted to build a new associative array I had to make sure I blanked it all and reassign everything well I can now do an assignment in a single step and that's a new instance of that associative array so in this case I'm saying index one is the word one index two is the word to index three is the word three so brand new instance of that index by table I haven't got to go and clean up the mess that was left from the last iteration so really quite handy and quite compact compared to the way we used to do things so that's an a teensy feature this is another thing I'm going to really struggle to explain and so this is one of those features that I kind of like for the geek value I'm not 100% sure how much I'll use it but I think it's really interesting so with a polymorphic table function rather than actually coding the implementation of the thing we're actually really coding the definition or the interface of how we interact with the table function a table function if you don't know is just any function that returns a collection would that might be a regular table function build the whole collection return it or a pipeline table function where we push out one row at a time this is slightly different and let's go through it so I've created the only table you'll ever need again I'm defining a package called poly PKG and in it it's got the only mandatory thing from a polymorphic table function which is a described function the purpose of this is i pass in a table and i pass out a description of that table the implementation for this is going to be really silly because what i'm going to do is implement it with just null what that means is whatever gets passed in i'm going to pass out the same structure so it's really achieving nothing but it's about as simple as you can make this with that package in place I'm going to create the polymorphic table function and notice there's no code in this all it is is a definition of function saying I'm going to pass in a table it's going to return a table and it's going to be pipelined and it's going to use this package to determine what really has to happen what the definition of this is what does that mean well it means now that function can be passed any table as an input parameter and it will do some work with it so for example if I were to select star from my polymorphic table function passing in debt I get at the hole of debt okay nothing dramatic there but what happens if I pass in amp well not surprisingly I get the output of M if you know anything about table functions you know that prior to this the output of the table function is fixed it's always got to have the same number of columns in it well now it doesn't have to so that's kind of neat for utilities let's try something else just to prove that I'm not leading you astray this time I'm putting the polymorphic table function into the package itself to make it a bit neater and what I've done is added an extra input parameter of columns I've got the describe once again that matches the table function I'm passing in columns and passing at a description the implementation of this all I'm saying is loop through the columns that are in the definition coming in and assuming the column is if the column is in the exception list then I don't want to show it so set pass through to false if it's not in the exception list I want to show it so this is a list of columns that I don't want to display so here what I've done is said select star from debt but exclude column location and that's exactly what it's done and here I've said select star from M but excludes salary manager and Commission and hire date and they've disappeared so it allows me to programmatically determine what I want to display one last example really quickly is adding a new column on to the output so I've got my input table again to the tape polymorphic table function and a describe and I've got this optional procedure called fetch rows what I'm going to do now is add a new column to my description so first of all I have to do this little thing which is to set this pass-through sorry yeah for read set to true for any column because I need to interrogate that in the fetch rows optional procedure but I'm adding a new column to the result set saying hey add this thing called JSON doc so what I'm doing is faking some metadata to say this is going to be there in the fetch rows I get the result set I loop through and I turn each row into a JSON document in its entirety and then associate that with this new column so I've programmatically added and populated a new column and now what I can do is select Department number in this fictitious column JSON document and I have a new column in the table as far as I'm concerned I can do the same with M and that one procedure is now capable of doing that for any table I pass in so I'm not 100% sure how often I'll use it I think if you're writing utilities or you're writing at all maybe something like Apex it would be super handy so kind of interesting I had the godfather of Apex nod when I said that so I must be right another thing we got in the lifespan of 12c 12c release 1 we got the ability to do approximate processing for count distinct in 12:2 we got some functionality that allows us to tell the database to start doing approximate processing for us so we can set some parameters where the database goes okay they're happy with maybe slightly off results we'll do a bit less work to get the results out and then in eighteen see we were able to do top end queries using approximate processing so what I've got that oops what I've got is a query - oh sorry I'm populating a table first you don't care about that with some random data and then what I'm doing is just requesting some data from that and I've got a just to show you what the data format is like so a count and a sum and we can see that essentially what I've got is for each department I've got five different record types from one to five and approximately equal numbers of rows and and some value in those it's random data so it's not perfect what I'm gonna do is first of all check the aprox for an aggregation setting in my session and you can see it's set to false so at the moment if I do something like say account distinct it's gonna do a count distinct so I've done a count distinct I've got a value I look at the execution plan and I can see I've done a full table scan a hash group buy an assorted rigueur and that's how it's got the data that's just normal what I can do now though is I can set up rocks for aggregation equal to true and without altering any of the code in my package it's set these extra parameters now if I run that query again I happen because it's simple to get the same value but notice now it's done a full table scan and an approximate aggregation so walk around sorry Mike Immy very easily I'm going to jump through the next demos because they'll take a while to explain and talk about the next section private temporary tables if you've come from something like SQL Server global temporary tables would have confused the hell out of you because people from SQL Server world are used to creating and dropping tables what we have now is the concept of a private temporary table oops notice that there's a initialization parameter of a prefix if my private temporary table doesn't begin with this prefix it's going to fail so if I try and create one called my temp table it doesn't work if I call it by default or a dollar PTT my temper table it creates it notice I've got hit on commit drop definition I insert some data I select from it it's all good I commit select from it it's disappeared okay so as soon as I've committed it's dropped the whole definition this isn't like a global temperature ball the metadata only exists in memory in my session another thing I could do is do one commit preserve definition what this means is I insert and select it's there I commit the data is still there in memory in my session but if I recruit reconnect to the database it's a new session that doesn't exist so it feels very much like a global temporary table but it's literally just in memory it only exists in your session depending on the definition very quick one DBMS lock sleep very useful when you want to pause execution the bomber was DBMS a lot contained lots of super important stuff like hey do you want to lock a table and you don't really want to give people that it's tough so in 18 C what's happened is that it's still there but it's also in DBMS session so every person gets access to do a sleep without having to have any extra privilege which is really handy external tables I've guess I've got a minute I'll show you the demo race through so I'm going to create some directory objects create an external table that accesses four different files query from that and I see that there's two thousand rows that are from Great Britain and two thousand from Ireland what I can do in 12c release two is I can actually alter the contents that the parameter settings of the materialized sorry the external table on the fly so here I'm saying just give me the location in the SQL statement of two of the files and I get different results and in eighteen see it gets even wackier because I can actually incorporate the whole of a materialized view definition into a select statement so even if I don't have privilege to create a table I can still access the data through a directory object in flat files by incorporate into a select statement this is both super geeky and super dangerous if you've accidentally granted people access to directories and of course I can change the definition to say hey just pull it from those two files in the Select statements and it works it's all good so I've kind of got to finish now so let's see what I had oh darn it case sensitive case insensitive queries we can actually actually access data in the database using collation for the first time if you used to SQL so yeah MySQL you know we've been able to do that for a long time but now what we can do is we can set collation at either at query time only in the query itself or at column level or table level or schema level and say we want to use a specific collation that can make it accent insensitive or case insensitive as well so pretty handy feature to have and makes us more in line with some other engines so this is really the tip of the iceberg I've picked a few things I think are kind of cool I would suggest you start trying to get up on this because I record costs a lot of money and if you're just using it as a bucket to hold rose that's a bit sad there's loads of functionality in there and more importantly it can do a lot of the work for you so you don't have to write code to do it and I'm all for that so I have that website Oracle based com that I mentioned if you're interested in getting the information that I've talked about today there is a very simple page Oracle based comm slash workshops you'll see here PDF slides an article I tried to have an article for every talk I do but of course this is just a list of demos so there isn't really an article that covers just this so I put a page on the website that is all of the things I've talked about today with link throughs to articles that actually explain all of this so if you're interested go to that Oracle based comm slash workshops click through to this and there's articles on all of this stuff and also how they vary in different versions so go nuts learn lots be a superstar and do very little work to achieve it and if you've got any questions I'll wait outside because someone wants to come to the front and start their talk thank you very much and see you soon [Applause]
Info
Channel: Oracle Developers
Views: 5,363
Rating: 5 out of 5
Keywords: oracle, oracle cloud, oracle developers, cloud, cloud computing, platform, infrastructure
Id: sHImNR6xxgg
Channel Id: undefined
Length: 45min 32sec (2732 seconds)
Published: Tue Oct 23 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.