Current section: Querying Data 5 exercises

Optimizing Prisma Client for Efficient Database Operations


00:00 We've actually already done a little bit with the Prisma Client. If you recall in the seed script, we create a new Prisma Client there. So you might think, well, okay, so that's just as easy as export, const Prisma, Prisma Client. And then of course, we need to bring that Prisma Client in. And that would be the case, except for the fact that we have HMR going on

00:19 and HDR, that's hot data reloading or revalidation. And what that means is when we make server-side changes, we don't shut down the server and then start it up again, we actually hot swap the existing code that's running with the new code that you just changed. That way, the changes are a lot faster

00:37 and you can very quickly iterate on different solutions. This is really awesome, but it also means that our module here is gonna be evaluated every time we make a server change, which means that the connection created by creating this Prisma Client will be made every time. So you change a file, it makes a new connection.

00:55 Change a file, that old connection's still there, makes a new connection. And it just keeps on adding connections until you get an error. And so for that reason, we have this singleton utility, which is pretty simple, honestly. It basically will call the callback that you provided

01:14 and assign that to this global variable. We're calling it YOLO here. But this global object, so that next time around, it does not call that value function and it simply returns what we got back from last time. So this has the side effect

01:32 of whatever that value function does, any of the contents of that value function, you won't get those updates. So if you change that and hit save, you're not gonna get it called again and so you won't get those changes. But most of the time, you're not changing that callback anyway. And so it lets us have a really fast iteration

01:51 of development, but also allow us to avoid making new connections every single time. So all that said, we're gonna say singleton and pass this as part of our function. And whoops, there we go, here we are. And then this is our client, which we will then return.

02:13 And, oh, right, we also have to give it a name. So we're gonna call this Prisma, there we go. So it's called Prisma and we're gonna create that client and then that gets returned. So saving that, we can actually go over here and test that that works out. So let's come over, look at our logs.

02:31 It looks like, yeah, we're seeing all of our users, awesome. So we wanna customize this client just a little bit. There are a couple of optimizations that we can make. So for one, Prisma will do a lazy connection. That means that it will connect after a little bit of time. And I want to connect immediately,

02:51 that way the first query that we make is faster. And so we're gonna say client.$connect and that will get our connection going right from the get-go. And then the next thing that I wanna do is I wanna configure the logging so that we get some logging on like slow queries and stuff like that.

03:08 So we're going to add some configuration for how logs are treated with Prisma. And so we've got our level query. We're going to emit an event that we can then listen to and log ourselves. We also have a couple others.

03:25 So we've got errors and info and warn. Now for the info and warn and error, I want those to, they can just go to standard out so that we can see those errors ourselves. But for the query, I want to listen to that event

03:48 so that I can log out to something myself. So we're gonna say client.$on, query. Now we get that event. So let's console log the event and take a look at what information is on that. So we'll bring this back so we get that query

04:04 and then come back here and we'll refresh. Oh, right, remember what I said earlier, any of the changes that happen in this callback will not get re-executed again. And so what we're gonna have to do is I will stop the server. I'm clicking the stop app and start app over here. And then we can take a look at that.

04:24 There we go. So now right here, that's the event that was logged. We have our timestamp, we have our query and our params, duration, all like just a bunch of useful, fancy information that we have here along with all the users right there.

04:44 So the thing that I'm mostly interested in is I wanna know which query was taking so long and how long did it take? So if there's a query that takes an especially long time, I wanna know about it so that I can optimize it in the future. And so I'm going to copy some code here because I don't think it's entirely useful

05:02 for you to watch how we accomplish this and we can kind of walk through this. So I'm gonna have a log threshold. This is exactly what I do on my own website, by the way. I have a log threshold that says, at what point do I consider a query to be slow? Now this will depend greatly on a number of things.

05:21 I believe in my website, I say 15 milliseconds, maybe 25 milliseconds. But for us, we're gonna say zero so we can see all these logs. And then I specify a color based on how much longer did it take? So if it was a 1.1 times the log threshold,

05:41 then we're gonna say it's green. If it's 1.2, then we're gonna say it's blue and so on and so forth. So that way we can kind of get a visual indication of how severe, how much longer this was than it should have been. And we're gonna color that with chalk so we'll bring in chalk.

05:58 And now, of course, we gotta restart the server again because we're changing something within the context of that callback function. And we come down here and take a look at that. Ta-da, it's red because it was zero milliseconds. So of course, this will be a lot more useful when you have more data

06:18 and your queries are more complicated and stuff. But it can be quite helpful to have that information in the logs as you're working through, working on different queries and things. So that's everything, I think. So let's just walk through a couple of the things that we did.

06:36 So first of all, we created the Prisma Client. That part's easy, not really complicated. We also called client.$connect so that we can connect early. We put all of this inside of this singleton utility so that we don't end up creating a bunch of disconnections every time we make a server-side change to our code.

06:56 We had to restart the server if we wanna have this function re-evaluated, which is perfectly fine because we don't often need to change this. Then we added some configuration for our logging following the logging information that we get from the Prisma docs. And then we added an event handler for whenever there's a query

07:14 so that we can log those queries that are extra long. And that is creating our Prisma Client. So we can actually start making queries to our database to load actual database data into our app.