 Welcome to Moving Data from Oracle to Postgres in Near Real-Time. Today we're going to talk about the importance of extremely scalable data ingestion, why real-time data transformations are critical, why complexity is no longer acceptable, and how to radically simplify data ingestion. My name is Lindsay Hooper and one of the Postgres conference organizer and I will be your moderator for this webinar. I'm here with Alton Dinsmore who is a senior data architect at Aqualum. Alton is a data veteran having worked at Oracle, Dell, EMC, MariaDB, and more. He has 40 years plus of design and architect experience around enterprise data solutions and applications. He's helped many companies implement successful projects around large data, high performance, large number of users, a large number of transactions and clustering, as well as high availability and disaster recovery. I want to say welcome to Alton. With that, I'm gonna hand it off to Alton. Take it away. Thank you Lindsay and thank you everyone for joining us today. Today what we want to do is talk about moving data from Oracle to Postgres in Near Real-Time. So what we'll do is I'll give myself a little introduction. Lindsay's already covered a lot of it and then we'll talk about some of the challenges, what our platform brings to the table for you, what we do with our Connect, our universal change data capture that we use, and some customer use cases and then we'll go into the live demo and we'll try not to keep it too salesy and keep it very technical. As Lindsay pointed out, I've been doing this for over 40 years. I've worked at many companies, Oracle included, with Rack, doing a lot around Rack over the years and all, but many mainframe databases even before Oracle came on the scene. And I've led projects, engineering teams, design teams, done just about anything in the world you can think about when it comes to putting things together. And some of the things I've really had to do in my past experiences work on resolving very large database implementation and issues around it, as well as high number of users. When you start getting into, in the early days, it was hard to get more than 2,500 concurrent users running on Oracle and worked on those 4,000 plus and larger implementations. So why Qualm? Why are we here today? Who are we? Well, basically, a Qualm was started by a bunch of data enthusiasts, right? So our founder and everybody are ex-DBAs, ex-data scientists, data architects, developers, all around the data side of the house. And the real thing that was very noticeable that our founder saw was the ability to liberate data. Sure, you can get to the data, but it wasn't really easy. And with the Qualm, he came up with a way to make the data ingestion process very, very simple. And to be honest, that's the same thing that drugged me over here, is how simple it is to actually get to the data and make it available for usage outside of the operational data stores. And the reason for that is, as we get in and we start looking at the challenges and anybody who's ever worked in a very large organization knows this, the challenges, some of the challenges we face, not all of them, needless to say is, is when you have these massive amounts of data being collected real time, and then people say, Oh, well, I want to, I want to pull those and I want to put them into a data warehouse, and then I want to be able to run analytics on them or AI or ML or whatever in the world you want to call it these days. It's, it's very, very tough to move large amounts of data real time. And trying to roll it on your own is a very expensive proposition requires a lot of skill sets. And it's just, it's just time consuming and very chaotic in a lot of cases. Then, of course, comes the challenge of, you know, while the data is good over there, but I need to transform it because I don't want to transform it after it gets into the data warehouse, because it's too, it's too much a problem for the analytics tools, I want to basically denormalize the data that I normalize for my operational data stores, I'm going to denormalize it so things run faster and quicker and it's more accessible and understandable on the other side. So doing that data cleansing and data transformation is also a real, real process of a problem for people when they have these large amounts of data coming from many, many data sources. And then when you get to the operational side of it, that's where it really gets to be a problem. Automating it, managing it, monitoring it, all the restart procedures, all the stuff that people normally do after the fact. I don't know in my career how many times I've seen people roll systems into production without even a backup. And so these are the kind of things that wind up coming at the tail end of the project that people don't really plan for in a lot of cases. But if you're going to run it on a daily basis, and it's going to be part of the infrastructure, all those things have to be put into place. And then when you get to the last one there, really trying to enable all those in an enterprise grade type platform with no coding required like Qualum has done is really, really tough. And that was the whole goal of building a Qualum is doing this in an enterprise grade with no coding being required. When you look at a Qualum, it's pretty straightforward. We look at things from a very simplistic format to me with sources being on the left and targets being on the right. And the business problem is I have data that's setting in operational data stores and cloud services, application, file directories, I don't care, anywhere just setting out there, OT sensors. And what I need to do is I need to get it to a target. And the most common target that people are usually going to think about is is I want to put it in a data lake or data warehouse, because data lakes and data warehouses have been around for a long time, 10 plus years. And so that's the one people think of. But it's not only taking that information and pushing it into data lake or data warehouse, you may have some AI or ML applications you want to do. You may also want to take some of that data and put it on a message queue for it to be consumed by another application that's grown in house. So the way we approach it is is we have a set of connectivity that we call our agents that actually connect to the sources. And those connections, depending on the source, most sources can do change data capture as well as real time streaming of the data. Now needless to say it can do badge, but the biggest challenge is is to do the change data capture and keep the streaming data going. So we talk more about it than we do the batch, but the batch is there. And no matter how you set it up, you can just say I said instead of running a streaming this time, I want to run it in batch. And we can do that in the demo at any point you want to. Then in the center, before you push it out, you may want to do all your ETL and ELT type or you may want to do transformations, you may want to filter data, you may want to do different transformations based on the geos that they're coming from, you may want to augment the data and enrich the data. So you can do all those kind of things. And then over on the right hand side, what you're going to do is is you're actually going to push it out to your target. And there's different ways that you can push it out to your target, you can append to the target, which in the case of a data warehouse that needs auditing capabilities, you really don't want to update the record that's there, you want to insert every record as being a new record. And you may want to merge or replicate things of that nature. And it really doesn't matter where you're going to put it over on the right hand side. And Postgres is definitely one of our major targets over on the right hand side, as well as being a source, but you know, mainly a target. In this case, we will be talking about target. And then for Aqualum, it really doesn't matter, you can either run it on prem, you can run it in the cloud, you can run it in the hybrid. All we really need is is we need the OS to be running. So it can run as a VM, it can run on bare metal. It really doesn't matter. It doesn't matter which VM you put it under, it doesn't matter, it's not going to affect what we're doing with the product. So with Aqualum, what you can do is is you can capture your changes from your data source, change data capture as it's referred to. And basically, change data capture is not a single technology. It is basically a philosophy of how you get data as it's changed. And how you get that change data differs based on your source. So for relational databases, we're usually going right directly after the log files and relational databases. But when we're looking at something like an S3 bucket or an NFS share, and we're actually bringing in, say, comma separated value files or JSON files or XML files, what you're looking for is you're looking for new files to be dropped or you may be looking for additional rows to be added to the file after you've did your initial capture of the the data itself. So with Aqualum, we can replicate your Oracle data to Postgres very quickly and very easily with very little work involved from your side of the house. And this gives you the ability to take anything is setting in Oracle and just push it into Postgres in near real time. Now, you can also take and you can replicate your existing operational Postgres and put it into a Postgres data warehouse if you would like to do that. And it's also very useful and a lot of people do this, taking their data from own prem, because that's where they're running their operational, but they have the data warehouse and data like setting in the cloud. So there's no problem doing that either. And you can actually even take events from your Postgres database and push them into a message queue, a publishing subscribe type system, whichever one you would like to do, you can push it to basically any of those publishing subscribe systems for everything, everybody to pick them up from there. And as I said, you can transform join and ridge, cleanse your data, aggregate your data, it really doesn't matter. You can do all those functions and features without having the right sophisticated code all done through the graphical UEML. And you're going to do that all in real time without the coding effort that people normally have to go through. So if we look at our agent, our connect agent that's doing the change data capture, depending on where you're going and what you're going after like, if you're going after Oracle, you're doing log parsing, log mining, the Oracle redo log is where you're actually getting the information from. And SQL server, we go differently and go after the change data capture information in my SQL. We basically set ourselves up as a read only slave. In Postgres, we're looking at wall file, wall file, and doing logical decoding on it and so forth and so forth. And then on things, when we get down to the individual flat files and all, in those cases, we've written some of our own CDC capabilities. So how do you get to CDC? Well, there's a couple of ways. You know, normally you're not just going to start with change data capture because change data capture is going to give you from the point in time that you request change data capture. So normally you're going to do an initial data load. And behind that will follow it with a change data capture synchronization. And some of the nice things about it is is that we never have to take the source offline or lock the source or anything else. We're just going after grabbing the data pulling it across. And once the initial loads done, then we start the change data capture synchronization right behind it. There's other things we can do here with multi table schema database replication. We can do the target table creation for you automatically. We can do DML synchronization. We can manage the schema evolution and you get to choose how you want to do that schema evolution. As well as we've talked about the real time data transformation, we can write to multiple targets and multiple formats. You have multiple right behaviors, whether you want to append to the target, whether you want to merge it or whether you want to do a true full replication, including deletes. And one of the things that sounds easy, but I think anybody who's ever tried to move from Oracle to post grass or from one database to another knows that doing the target data type conversion is always a pain for people. It's something that you really have to look at closely. So we do automatic data type conversions. And then, of course, the user does have the advantage or the ability to go in and modify those data types. So if you don't like the default mapping we gave it, if you want it to be different in the target, that's something that you can set up and change very easily just going through the GUI. And as I said, you know, we have a zero coding user interface, graphical user interface, which you'll see here in a minute. And then one of the things that a lot of people never talk about is is the monitoring and alerting. It's built into our platform. We monitor all the different phases, all the different steps. And we have alerting that can be set up so that you can get notified if anything does not fall within the areas that you wanted to. So any kind of warnings or any kind of failures, you will get alerts for those. And one of the big things, I think, when you look at a qualms is we have an exactly once guarantee. A lot of products will guarantee that they'll do the record only once, right, that they'll get it once, but they won't always guarantee that you get every change always replicated in process just one time. So some will do the exact once up to the target, but they don't guarantee that you get every row on the change that came in. Others will guarantee that they'll get every change, but sometimes they actually push out multiple records to the target. Coming from, you know, Oracle background, you know, exactly once is exactly what I want. I do not want stock trades being processed or dropped multiple times. So and along with that, we have a full H A topology. So it doesn't matter what fails, whether it's a source, whether it's target, whether it's one of our components, whether it's the servers, full H A and with that, a full restart to guarantee only once processing. So it doesn't matter where we fell. You're fully insured that everything will process only once. A little bit only because people always want to know, you know, who's working with us, what we've done. So we have a lot of different many companies that we work with in different areas. They're not all within just a single one. And we have some real closely working partners. Some examples of some things that have that we've actually done for our customers and the oil and gas. One of the things that they wanted to do in this company was they really needed to get the IOT sensor information processed very, very quickly. Previously, it was taking 15 minutes or more to get the IOT data and 15 minutes is a lifetime when you're actually looking at equipment, sending out pre, pre pending errors, you know, failures are about to occur when you're dealing with this expensive equipment. So getting it in near real time is exactly what people needed to do. So as you can see the pain points here, 10 minutes, latency at best, no matter what they did. And the problem was the whole data ingestion process was very time consuming and they're having more and more sensors added every day. So what we did was we actually took data from a variety of sources, including Oracle SQL Server, DB2 and many others. Real time and batch into NEM SQL in this case with sub second latency for data ingestion part into the system and that that really, really improved the whole entire process. So one second or less streaming latency, 20,000 changes per second and, you know, real time reporting and analytics being performed on this data. And as you can see there, they tested six products and Equalum was the only product able to deliver on both latency and performance. Media, broadcasting, what they really want to do is go in and actually look at how social media is impacting the viewership of their shows. And so it was a very interesting approach at this. Kind of like, you know, they've been doing for years, but this time they needed more real time because as they put it out there they needed to see the impact. So ingestion from over 10 different sources. This one's in a Azure SQL data warehouse. They tried this internally and the problem is and I think a lot of people find this out once they go down this road. It takes a large skill set and then the problem you got is turnover in staff. That skill set leaves and so it really, really is tough when you try to do it yourself. Real time was enabled. They got a unified view of the data and we empowered them in a single week what would have taken them years in house to build. And then we got a large manufacturing conglomerate, same kind of thing, you know, so different customers that they had to process and all taking a lot of sensory information and data from S3 in real time and batch into Hadoop on AWS, 16 different data sources, 120 different data manipulation steps. And it, you know, it took them a lot of time to actually process all this information. And so when they brought us in, what they did was they took what they had running currently and moved it over. They saw a 15 times improvement in performance, a 10 times cost reduction, a 300% improvement in productivity. And it was real time and self service also, which was really important. So we look under the covers, what you'll see is you'll see a column has the sources and targets on the left and right. But in the center, what you'll see is is the engine itself working with the connect engine. And the connect engine when we're doing streaming is going to move the data into a kafa topic. And then we're going to work and run our own special code setting inside of Spark to do the actual manipulation and the flows. And we use Zoo Keeper along with HDFS to have guaranteed high availability. This is the example of the just the GUI, UF UI, so that people can actually see it and we'll go into the demo and see it in a greater detail. So what we're going to do is we're going to go over to the platform and actually look at it. When you come into Equalum, you come into the dashboard, normally on Port 9001. And there's two views. There's the replication group view and there's the classic view for people who are really just looking at moving large amounts or large number of tables, say from Oracle to Postgres, they would probably use the replication method. And what we're going to do is we're going to go through that first. What I want to do is I want to lay out, in my experience, working for Crunchy and MariaDB, you know, Postgres and MariaDB is my sequel type database. One of the things that there's two main reasons that I saw that people wanted to pull data off of Oracle and get it into Postgres. And one of them was they wanted to take the application and modernize it and they wanted to rewrite it so that they could actually move off of Oracle. That's one of them, which replication groups are perfect for that, right? Because I'll need to take the data, I need to push it across and I need to change data capture to keep the data going while I spend the next six months to a year and a half modernizing the application, rewriting it, maybe even containerizing it and putting it in Kubernetes and get microservices in place in the new release and run it against Postgres. The second reason is that they have applications, sometimes packaged applications, a lot of times Oracle's applications that will always wind up running on Oracle. And what they want to do is they really want to go into a data warehouse in a data lake type environment with that data into Postgres because setting that up into an Oracle environment is more Oracle licenses and they don't want to have to spend all that additional money to set it up. So two different scenarios. So the first one we're going to go through is somebody who just basically wants to set up and replicate a group of tables from Oracle or whole Oracle database and replicate it into Postgres. So first thing is, is setting up a source and target is very, very easy. Like for the Oracle, it's nothing that you would think out of the ordinary. It's the host, the port, the service you're going after the username and password. And that's pretty much it. Now there's a lot of advanced features that you can get into about schema evolution, your lag objectives for performance, parallelization, all that stuff. And you can also even set a custom change data capture position should you need to grab data out of Oracle, but you don't want everything. What you want to do is you want to start at a starting point, an SCN within Oracle. So if Oracle had 20 years worth of data and you really want to start your data warehouse or your new application with just the last five years worth of data, you could give an SCN. OK, so what we're going to do is, you know, that's very easy. We can do the same thing on the targets itself. We can come over here. We can look at, say, the Postgres target here and you can see it's the host, the port username, password, the database and the schema, the default schema we're going after. So the first thing is, is I've got Oracle and I want to just replicate it straight in. Easy, simple, as quick as possible over to Postgres. The easiest way to do that is to add a replication group. All you do is you click on, click add for the replication group there or replication group over here on the left hand side. So we'll just add a replication group. I'm just going to call it RG1 and I'm going to select my source being Oracle and I'm going to select my target to be Postgres and I'm going to put it in the public schema. Now, how do I know what I'm going to get out of the Oracle? Well, we do it through table pattern matching. So I can click plus to add a table pattern and I can have as many of these as I want. I can select all and I would replicate everything out of that Oracle database. I can select none. And in this case, what I'm going to do is I'm going to select schema OT and I'm going to come over here and I'm going to do everything percent and I can include or exclude. So at this point, I can say generate the list and what it will do is it will generate me a list of 15 tables. OK. Now, I noticed there's a couple in here that I really don't want. Now, I can I can get rid of those just by clicking and they go over here. I'm going to put them back in just to show you I can come up here to the pattern matching. I can add another pattern matching same schema, OT schema and I'm going to do a Q percent. And this time I'm going to exclude it. Now, I had 15 tables. I'm generate the list. Now I've got 13 tables. So these are the 13 tables that I want to basically replicate into Postgres. So all I do is I click Validate Table. It will go through. It will notify me of any validation issues. And this checks privileges and capabilities within the target. It also checks to see what's being done with the current replication to make sure you're not going to step on each other without you knowing about it. And at this point, I can say create. When I create, I see my replication group one get created here. If I come over to the replication group, you can see each one of these are getting created as we go along. And what it will do is it will tell us that basically all these replications are now working. So if I go over to the beaver here, OK, and I go down to my Postgres here, my Postgres in my public and I refresh my schema. I can now see these tables are over here. So if I go to orders and I go to the data, the data is over here already. Now I can sort the data. So I'm sort it, OK, and order ID three thousand and fifty three is the last order ID that's in there. So I just in a matter of just a couple of minutes started replicating. It did the initial capture and started replication for 15 to 13 tables, right, in four code of Postgres. Now I'm going to go over here and I'm going to start updating the Oracle tables, right. So that should start updating the Oracle tables. And if I come over here to the beaver and the last one was 30 53. Now I'm at 30 56. So all the data is getting pushed across as we're doing the replication. So I hope that helps you out a little bit. It's pretty easy to come over here. You can see the replication group. You can see the data, the equivalent platform tells you exactly what's going on, what it's capturing and all as we go across. Now that's the first thing, right. Now I can switch over to the classic view, right. And I can take any one of these that I've got here. And if I want to, I could actually update it right now. This is published, which means I'm on version one. It's published. I cannot edit it, but I can click edit and I'll get version two. And on version two, I can come in here and I can choose an operator and I can do a transformation and I can basically start doing transformations right here on the fly if I wanted to. So it's even though it's a very simple generation to source the target, I can come back and upgrade those at a later time. Now, if I want to, what we'll do is we'll come in. This is the classic view. OK. Within here, I've got a I've got one running right now, right, that is basically taking some order information, order items, looking up, adding product information to it, joining it and transforming it. In the Qualcomm platform, anytime you click on preview at this point, what it's doing is, is it's actually building a job, submitting it to Spark, Spark's running it against the katha topic and bringing the information back. And I don't know if any of you've ever played around with Spark and all, but count how long it takes to actually look at this data on one thousand one thousand two and about two seconds. We've created a job, submitted it to Spark, ran it in Spark and then returned and Spark's looked it up in katha, grabbed the day out of katha and brought it back to us. For anybody who's ever played with Spark, they're going to go, oh, wow, that's fast. Normally it takes me 20 seconds just to get the job started in Spark. So I've got orders. I got order items. I've got look ups here. So what I'm doing is, is I'm actually joined based on the product key and getting the product name, things of that nature. I've actually joined the two tables together and I've joined these two tables on order ID and for anybody who's ever played around with streams, you know that the data is not always guaranteed to be at the exact right time. So you need to put some kind of windowing. In this case, I did five minute windowing functions. So, you know, within five minutes, I'm assuming everything is going to be within the same span. And then transformations, you can do all kind of transformations and equal them against your data. So you can change the type. You can add additional columns. In this case, I did the length of a concatenation and also used one of our user defined functions called greet me. So if you do need to write code, you can create your own user defined functions plus also you can write code in pre and post processes if you need to for something special. So in this case, this workflow is actually going out and writing into a Kafka topic at the current time. Now, if I want to, I can come in here, edit this flow. And now I'm on version two. I can delete my target and come back over here at another target and I can point it to Postgres this easy. I now edit where I want it to go in Postgres, right? So I can say I wanted to go into the qualms schema and I can say generate the create table statement. And instead of this, I'm just going to call this the pre preorder item info. OK. And if you'll notice it creates the table, it does the grants, everything else and I can execute it. And at this point, I have now created the table within Postgres for us to load into. And there's our preorder item and I can go to mapping. I can do a couple of things. One is is I can, you know, change around what we're doing. In this case, I can change the mapping if I need to and the type that it is. But in this case, I'm just going to say OK. I'm going to say OK. I'm going to save it and then publish it. And execute it. And. Oh, and I did one thing wrong, go to my flow executions here and I'm going to pause it. I'm going to resume it and I'm going to reprocess all the events. And what that will do is, is that will give me my initial capture again, pushing all the data into Postgres, because I had pushed it earlier into the kafa topic. And so this case, we will be pushing it in now. And you can see that it did the initial capture and then went to the change data capture. So if we come back over to the beaver and we go to the equal schema. And we go to our pre-order item table. There's all the information that we brought across from the the new schema, changing it, pointing to kafa, pointing it directly into Postgres. And as you can tell, you can do any numbers of transformations and changes that you would like to do. So within the column, some of the good things is, is we have our complete metrics, which will actually come in and it will tell you what's going on. It's, you know, our metrics are being populated into Prometheus and then are being consumed and displayed through Grafana. And for all you folks who know Prometheus and Grafana, you know that pretty much anybody can grab Prometheus metrics and Grafana has its own dashboards that you can create. So if someone doesn't like the standard dashboards we provide, they can always define and grab their own dashboards and do whatever they want to. As you can see down here in the user topics, you can see what was going on in each and every user topic within the kafa platform. So this is all of our vent stream data coming in. This is what we're doing at the current time. And if I go in there, you can actually see a little bit more of what's going on. You can see all the RG1 topics that we have and things of that nature. And it's really good because what we do is is we give you not only kafa, but the agents, which are actually collecting the information so that you can see what they're doing with their change data capture throughputs and things of that nature, their overall throughputs, so forth. And same thing with our flows, streams, targets, all the information is collected and displayed. And then, of course, within the notifications, you can set up notification rules. You can set up like this is a notification room on the target when it's a warning or critical. Email myself, right? When I have a flow with a tag of orders on it, on anything, I want you to basically notify orders at the quality.io and they're real easy to do. All you do is click on the notification tab, the replication group, if we get any kind of warnings or whatever. So if I get anything on the replication groups, I want it to if it's a warning or critical, I want it to email me. I don't care about info. And that's how easy it is to set up. So one of the problems that that I've seen all my life, putting databases in everything else is is usually had to go and develop another pack or buy another package to actually monitor and do anything with it. You know, just ask Mark Benny off about riding patrol on his on his hiatus from Oracle and then turning that and eventually getting to salesforce.com. But, you know, you got to do these things and they have to be monitored and they equal on platform installs all the components, manages all the components and gives you full graphical interface to it. As you can tell from the top, we're displaying a lot of the Prometheus in metrics and all. We're doing this through Java about CPU load, memory utilization, space usage and so forth. But you also notice on each one of the tabs or cards here, like on flow executions, we've got 14 streaming executions running at the current time. We've got none of them pending. We got none of them paused and we got none of them in error. On the batch, you can see we've got none of them active, none queued, we had four successful in the last 24 hours and had three that failed in the last 24 hours in the same way with the sources and targets. I've got five sources active, none pending or paused in the same way with the target six of them active and paused. So the other thing is alert management. OK, we try to display in each one of the locations you're in, but there's an alert management and what it will do is it will tell you the information, right? See here my target snowflake and this is because I'm running on a single node because I'm not in high availability notes. So I get a warning because of the process telling me that it's not so you can see each one of these things are highlighted for you. And like I said, you know, you can click on the alerts within each individual area and you can just say a knowledge all and what it will do is acknowledge them and remove them. OK, I know I went through a lot of this stuff really fast, but I want to make sure I had plenty of time for questions and answers at the end of the session. So real easy to set this up. It's real easy to monitor. I don't know if any of you have looked at moving stuff from Oracle into Postgres, but if you have, you know, you move the data, but then the real problem comes the continuous feed from the Oracle side over into the Postgres side. And that's where you got to run out and grab some more tools or write a lot of code and then you get into the problem with the restarting and guaranteeing nothing gets dropped. And that's where we come in. We handle all that. We make it simple, easy, you know, very, very manageable. It does not take a high level of coding skills in order to be able to do this process. OK, we got a few questions that have just come in. Guys, keep them coming. So the first is how will metadata get copied to Postgres from Oracle? Depends on what you mean by metadata, right? So the the DDL of the original create table we do automatically for you or like you saw when I changed it from Kafka to Postgres, it generated the create table statement and I can modify that to any method I need to before I execute it. But when you when you create a flow like pre-order info here, when you when you create these flows, well, we'll take one of the RG ones here. When you create these flows and all and you look at them, one of the things that you do is as you set up even in the source, what you want to do with the DDL that comes in, right? So in the case of this one by default under advance by default, I have three choices that I can do and this is where I get my choices every time. I can do do nothing with the DDL. Don't evolve the schema. I can evolve the schema to the stream of data, but not anywhere else. And then I manually have to take care of whatever is going on or the last one, which you probably want to do in the case of just doing straight old replication, right? From source to target, you want to do end to end schema evolution so that whenever I add a new column in the Oracle table, it would automatically add the column in the Postgres table and it would then automatically take those new changes with that column and populate that new column in Postgres. And that's what you would more than likely want to do in your replication. So that it's it's easy to set up by default, but it's also very over rodable based on the workflow that you're working on. Great. So the next one is when migrating from Oracle, will this outperform their Golden Gate CDC tool? Yeah. In the release that I'm running right now, this particular release, we're using the log miner to read the Oracle log. OK. Our new release, which will be out this week, which our customers won't be on for a little while, but it's releasing this release, reads the Oracle redo log binary just like Golden Gate has been reading it for years. And so at that point, it will be the same performance as the Golden Gate change data capture. Great. And I have one more right here. The GUI abstracts away the spark code for ETL processing. What if I need to run some custom pie spark transformations? Does it allow me to do this? Yeah, you can. You can basically when we were in this process here and we're in the transformation, right? When I come in here, I can basically in the functions that I've got, I've got custom code. I can write anything I want to here and put it in Java or JavaScript and drop it in as a user defined function. And then I can call it for every single thing that I want to do. So I can do it through the Java interface here. There's also pre and post processing that I can do before I start processing the data or after I start processing the data, depending on what I need to accomplish. And there's probably a couple of other ways that you can do it. But those are the easiest ones to do right out of the box. Now, there's no way that an off the chef package will have proprietary algorithms, especially when you look at like banking and you look at the insurance companies and even stock trading and all. There's no way that anybody is going to be able to get all their proprietary algorithms because otherwise it wouldn't be proprietary. So you have to have a way for people to have those proprietary algorithms and be able to put them in for the transformations for like customer ratings and rankings, credit scores, all that kind of stuff. So there's plenty of places to do that. Fantastic. So with that, I just want to thank you, Alton, for spending this time with us. And I want to thank all of you for spending your mornings or afternoons or evenings, wherever you are with another PostgreSQL conference webinar. So enjoy the rest of your days and I hope to see you on the next one. Thank you.