My name is Dana, so I'm another one of Andy's PhD students and probably going to be the last of his PhD students to present to you before he gets back.  So before we start, a couple of reminders. The first is that Project 3 is due on Sunday, November 17th before midnight. We also released homework for last week and it will be due on November 13th before midnight. Any questions before we begin? All right, so today we are going to talk about multi-version concurrency control. Just make sure I adjust this here. So the first thing I want to point out about multi-version concurrency control is that its name is a misnomer and this may cause some confusion because it's not actually a concurrency control protocol like the ones that you've been learning about in the past two lectures, which are time stamp ordering, OCC, and two-phase locking. Rather, it's a way to architect the system when you have concurrent transactions running by maintaining multiple versions. So recall from last week your discussion of optimistic currency control where transactions maintain a private workspace and any time they read or wrote to an object, they would copy that object into that private workspace. Well, multi-version concurrency control is similar to that idea. Here, instead of having a private workspace for each transaction where we maintain these different versions, we're now going to have the versions be part of a global database and we're going to determine whether some version is visible to a particular transaction. So MVCC is used by almost every new database system that's been built in the past ten years or some variant of it, but it's not a new idea. So it's actually decades old and the first reference to the idea was in a dissertation by a PhD student in MIT in 1978. So it wasn't until the early 80s that the first implementations of it actually came out and those came out of a company called DEC and they were called RDBVMS, which stood for Relational Database for VMS or VAX, which was an old operating system. And the other product was called Interbase. So DEC used to be a major computer company. It was bought out by Compaq in the late 90s and then a few years later bought out by HP. So it's no longer around, but it did some major pioneering work in database systems. So both RDBVMS and Interbase were built by a guy named Jim Starkey, who was also credited as being the inventor of jobs and triggers.  He later went on to co-found NUODB, which is a new database startup and it also happens to use MVCC. So DEC RDBVMS was bought out by Oracle and is now known as Oracle RDB. And Interbase was eventually sold by DEC. It went through a few different holding companies and finally was open sourced. And so now it's known under a different name. Now it's called Firebird. So it may not be as well known as my sequel or Postgres, but it's one of the earliest open source databases out there. And Andy had this whole fun fact in there from last year, so I'll go ahead and say it. So if you've ever wondered why the Firefox web browser is named Firefox, it's because they were originally called Phoenix, but then they had to change that name because it conflicted, you know, with another system or another product. So they changed it to Firebird, but then they had to change it again because it conflicted with this database system. So finally it was called Firefox. So the main benefit again, like what you have to understand about MVCC is that writers don't block the readers and the readers don't block the writers. So it's only when you have two transactions trying to write to the object at the same time that you have to fall back and rely on one of the concurrency control protocols like two-phase locking. So again, you only need to do this when you have a right-right conflict. So at a high level, the way this works is we're going to assign time stamps to transactions when they arrive in the system and then we're going to provide it with a consistent snapshot of the database as it existed at the time that that transaction arrived. So this means that they won't see changes from transactions that have not yet been committed in their snapshot. And just to clarify, this is a virtual snapshot, so it shouldn't be confused with, you know, a physical snapshot or copying the full database to another location and then running that transaction on it. So again, this is just virtual. So MVCC is really useful for read-only transactions because the SQL dialect allows you to declare when a transaction is read-only. And if you do this, then the database system does not require you to get any locks or maintain the read-write sets. And this works again because it has a consistent snapshot and will only see the changes that existed at the moment it started. And this makes these read-only transactions really efficient and also really fast to do. Yes? How do you recommend a virtual version of the snapshot? I mean, just like I mentioned a minute ago, it's essentially just maintaining a version table or version-made data information. And it's very similar to OCC where you understand the read-and-write sets. And we're going to clearly go over this in a lot of detail in the following slides. This is going to be the topic of this lecture. Yeah? So it's the... We're talking about two reads here. They will read the same snapshot, the same version. So snapshot, you know, it's more commonly, I think, referred to as the version, you know, of the two-bull or database object. When do we bring in a new version of the snapshot? I mean, we're talking about two reads here. They will read the same snapshot, the same version. When do we bring in a new version of the snapshot? Well, can...  And we'll actually... That is the first thing we're going to cover. And I'll answer any other questions you have afterward. All right. So just to finish up on this slide, another advantage of MVCC is that you're able to support something called time travel queries. So these are queries that actually let you ask the database system, for example, what was the state of the database, you know, three days ago, three years ago, and using this versioning, they can actually answer these sort of queries. All right. So the idea of time travel queries was first... was an idea of Postgres, and it originated from Postgres in the 1980s. But Postgres actually removed these time travel queries from their current product, like as soon as people outside of academia started using Postgres more heavily. Can anybody guess why? Well, so the reason why is because essentially what you have to do to actually support time travel queries is you never throw away old versions. So you never garbage collect, right? So over time, you know, the more and more transactions that commit, your disk space will be filling up very quickly, and eventually it will be full. And probably very quickly, depending on the speed of your transactions. And the other thing is that time travel queries are not really needed by a lot of applications. You never really look at... You never go to a website and say, like, okay, I want to know what this web page looked like three days ago. Not in most use cases. But Andy mentions that one common use case for these time traveling queries is in the financial industry.  So these time travel queries actually allow them to very easily query the database and figure out what, you know, some of money, what their total revenue was, or whatever they want to look up, you know, over the past seven years. All right, so in the next two slides, we're going to go over two examples. And what I really want to emphasize here before we start is that MVCC is independent from concurrency control protocols. So the purpose of these examples is just to basically show you how we, you know, update versions and timestamps in the table and also basically, like, how... Sorry, how we figure out which version... How we figure out which version is visible to the particular transaction, right? Which version of the tuple is visible. So this first example, we'll see how this is going to work. So right now, like, the first thing to point out is that now we have this version field, right? So we can see in this version field that it's assigned to A0. So this means object A version 0, right? So we can assume that some other transaction has written the value 1, 2, 3 to the database and whatever transaction wrote it was assigned a timestamp of 0. And we'll go over why in one second. So we also have a begin and end fields. And so these are just timestamps. It doesn't matter if they're logical, physical, hybrid, as long as they're always increasing and follow the other, you know, I guess our valid timestamps, right? Like you learned in the past few lectures. All right, so let's begin. So when a new transaction arrives, so we're going to be looking at transactions T1 and T2. So here T1 arrives and it's assigned a timestamp of 1, right? So now we're going to begin. Okay, so the first thing we want to do is we want to do a read on A. So what we're going to do is we're going to consider, you know, transaction once timestamp, which is 1, and we're going to take a look at our table and figure out which tuple is visible to it by finding, you know, where its current timestamp is between the end and between beginning and end. So in this example, the beginning is 0 and the timestamp of 1 is between 0 and the end, which is infinity, right? So it's going to go ahead and read version A0, right? All right, so now we have transaction T2 and we're going to assign it timestamp 2. So the first thing we want to do here is we want to write A. So at this point what we're going to do is we're going to create a completely new version of A, which will be A1, right? Because we're just incrementing the version counter. And so what we're going to do here is the beginning timestamp is going to be set to the timestamp of T2. The end timestamp will again be set to infinity and then the last thing we're going to do is we're going to update the end timestamp of version A0 to also be timestamp of 2, right? For transaction 2. All right, so one thing you might have noticed that we're missing so far is, like with just, you know, the information that we had so far before this transaction status table popped up, the one thing that we're missing is that we don't really know the current state of the transactions and the database. So for example, you know, the transactions here are currently active, but what if they aborted? You know, then you would have to go back and reverse the timestamps accordingly if it was aborted, right? So as you can see, here we're just going to start filling out the transaction status table. At this point both transactions are active. Then finally we're going to do this read on A. So what version is it going to read? Anyone? Right. A sub zero, because again it's timestamp still lies between the beginning and end here. So it's going to go ahead and read version A0. And finally it's going to commit. So at the very end after this commits then transaction T2 will commit. We'll update the status table and we can blow it away eventually. So for the second example we're going to start with sort of the same setup, right? So we have transaction T1 with timestamp of 1 and in transaction T2 we're sending a timestamp of 2. And it's the same state in the database table and so far we're just starting transaction T1. We're saying it's timestamp to 1 and the status is active. So first we're going to do a read on A. I think at this point it's pretty clear that we're going to read version A0. And next we're going to do a write on A. So again just like in the last slide we're going to create a completely new version and sort in our database table where it's going to be version A1 with value 4, 5, 6 and the beginning timestamp will be a 1, right? It will be whatever this timestamp is and we will sign to infinity again. And the last thing to not forget is that we need to go up to A0 and assign the end timestamp to be the current timestamp of transaction T1, which is 1. Alright, so now we're going to begin transaction 2. So the first thing we're going to do is a read on A. So in this case which transaction is it going to read? Or sorry, which version is it going to read? Excuse me, A1? And why is that? Yeah, so in this case it's going to be... Oh, sorry, I forgot. So one thing that we have to pay attention to and this is a little tricky right now. One thing I forgot to mention at the start is I understand you guys didn't have time to go over isolation levels. So Andy wanted you guys to just review the slides and also the lecture from last year. So I'm just going to provide some high-level hints for isolation levels for when you go over those slides and the homeworks, right? But it might not make full sense at this point. But basically like at a very high level, depending on the isolation level you have, it may choose either version A0, A1, but let's assume it's sort of... it's the strict serializable... or excuse me, serializable isolation, which is sort of what you guys have been using up until this point. At this point it has to read A0 because A1 has not yet committed. All right, so now we're going to do a write on A. And so in this case, what's going to happen next? Well, again, here we have a write-write conflict, right? So assuming we're using 2PL, T2 is going to have to solve until T1 commits, right? So let's keep this going. So now we're back to T1. We're going to do a read on A. And in this case, it's going to just read the same version that it wrote a couple of minutes ago, right? And then it's going to go ahead and commit. All right, so now we can go back here and we can go ahead and now we're going to create the new version A2 with value 789. We're going to assign it the timestamp of 2 with an n timestamp of infinity. And we're going to update the n timestamp of A1 to 2 as well, right? So at this point, you know, whether T2 actually commits or not is really dependent on the concurrency control protocol as well as the isolation level. So that's something to keep in mind. But really this example, the purpose of this example is just to show you how we update the object versions, maintain the transaction status table, and also figure out which tuples are visible, right? Any questions on this? All right, so as I mentioned, a few, oh, yes. So like you said in a previous slide that a writer won't block a reader, right? So when you are updating that version table, so don't you need to have locked on that table? Because like if I'm like, if I did a write and I am like updating a value, like I'm adding a final value to...  So this right top corner table, if I'm a writer and I'm updating this table and somebody is reading this table, then don't we need to have locked on this table? Oh, well, so this, again, this is a very high-level example right now and there's actually, we're going to go into how you actually store this information later on in this lecture. So that will answer the question. Basically it's, in some cases, yes, you do need to consider locks. It really depends on how you're actually storing this version information. So if we don't cover it in a few slides, because there's multiple ways to do this, so I don't want to just list them all out now. If we don't cover it in a few slides, please ask your question again. All right, so again, like MVCC or its variants are used in almost all new database systems and these are just some examples of the systems that use MVCC. But what we really want to emphasize for the rest of this lecture is that MVCC is a lot more than just maintaining the timestamps that I showed you in the previous two examples. There's a whole bunch of other design decisions that you have to make in order to actually implement a system that supports MVCC. So we're going to go over those next. So what exactly are these design decisions? Specifically it's what concurrency protocol you're going to use, how you're going to maintain and store the different versions, which relates to the question that was previously asked, how you're going to clean up the old versions, once they're not visible to any transactions anymore, and how you're going to ensure that the indexes point to the correct version. All right, so the first thing we'll cover is... Skip that one. Okay, so that's what I thought. Okay, so the first thing we're going to cover is concurrency control protocol. All right, so this is basically... Oh, I'm looking at the... Sorry, I'm not used to this present review. My bad. Okay, concurrency control protocol, this is our first consideration for our design decisions. So these are the concurrency control protocols that you guys have been studying for the past two weeks and the past two lectures. And again, when you encounter a right-right conflict, you need to use one of these protocols, whether it be two-face locking, OCC, or timestamp ordering, to figure out which transaction should be allowed to write to that object and what isolation level you're running at. So we're not going to go into much detail on this, since you've just been covering it very recently. So the next consideration is version storage. So for version storage, what we need to do is figure out for a particular tuple version what should actually be visible to us, right? So let's assume for now that we're doing a sequential scan on the entire timetable and we want to know where to find the version of a tuple that we want. So the way we're going to implement this is we're going to maintain an internal pointer field that will allow us to find the previous or next version, we'll go into that more, for this particular logical tuple. So you can think of this as sort of a linked list where you can jump on into, you jump on in and land on the head and then you can follow the pointers in the linked list to find all of the different versions that are currently being maintained. So indexes always point to the head of the chain and, oh my God, I did it again, I'm so sorry, okay, technical difficulties. Alright, so indexes, like it says here, will always point to the head of the chain. Whether the head is the oldest version of the newest version of that tuple depends on the implementation. So there's different approaches that determine how we're going to store these different versions. So we'll go more into that next. So the first and simplest approach is called append-only storage. So this just means that every time we create a new version, we just copy the old version as a new physical tuple in our table space and update it. So then we update pointers to say here's the next version. And we're going to go over examples of all three of these in the next few slides. So the next approach is called time travel storage and this is where you have one master version table that is always storing the latest version of the object or tuple. Then you copy out older versions into a separate table that we're going to call the time travel table. And then at that point you just maintain the pointers from the master version of the table with the latest tuples to the time travel table. And so the last approach, which is the one that Andy prefers and thinks his best is called delta storage. So you can think of this as a diffs and git where instead of just copying the old version every single time and updating it you're just going to maintain a small delta of the modifications from the previous version. So we'll first go over an example of the append only storage. So again this is the simplest approach and this is also what Postgres uses. So each new physical version is just a tuple, is just a new tuple in the main table. So let's say we have a transaction here that wants to update object A, right? So the first thing it's going to do is it's going to find an empty slot in the table space and then copy the values from the current value of A, which is A1, right? That's the most recent value into that table slot. And then next it's going to copy the modified value into that table slot. And are we done yet? Not quite. The final thing we need to actually do is update the pointer to point from the older version to the newest version that we currently installed. So another aspect we must consider here in order to store these versions. So in this example A is considered the head of the version chain and in this example we're specifically ordering these oldest to youngest, right? So an alternative would be you can order them youngest to oldest. So if you're looking for the newest tuple in this case you actually get to the pointer where you get to version A0 and again you have to follow the pointers all the way down to the newest version A2. Does that make sense? All right, so like I just said the previous example used oldest to newest but you could also use newest to oldest and there's performance implications and tradeoffs for both of them, right? So with oldest to newest all you need to do when there's a new version is to just append to the end of the version chain, right? This is very simple. Append the new tuple and update the pointer to point to the newer version from the older version to the newer version. And this is a really easy operation to do. But if you do newest to oldest then what this means is that you have to add the entry and update its pointer to point to the old head, right? But now you have to actually update all of the indexes to point to your new version since again like we said a few slides ago indexes always point to the head of the version chain, right? So this means a lot more updates in some cases. All right, so for time travel storage this is the next approach we'll cover. And here we're going to have a main table that always has the latest version of each tuple. And then we'll have another table called the time travel table and this is where we're going to maintain older versions and copy older versions as they get modified in the database, right? So for this example let's say the transaction wants to update object A again. Same as last example. Then we're going to copy A2 into the free spot in the time travel table and then update the version pointer to point to the oldest version of tuple A. Then we're going to overwrite the master version in the main table to be the new version value. And finally we need to update the there, new version value. And then finally we need to update the pointer to point from the new version A3 to the version that we just installed in the time travel table which is A2, right? For each object or is it almost like a pen table? It would be in a pen table. Alright, so now we'll move on to the last approach that we're going to consider which is delta storage which again, this is used by both MySQL and Oracle and like I mentioned it's the one Andy thinks is the best option. So what's going to happen here is every time you do an update you're just going to copy the values that were modified into the separate delta storage segment that you see over here. So to update A we're first going to update its version value into the delta storage, right? So we're going to copy over its value so instead of storing the entire tuple we're just going to create a delta that states which attributes in the tuple were actually modified. So in this case there's one attribute so that was now reflected in the delta storage segment. Then we're going to update the actual value in the main table and also update the pointer from the new value into our delta storage. So similarly if we want to now install a new value a new version then we need to do something similar to the time travel table scenario which is specifically we append the new version update the value again and now we're seeing its version A3, right? But we also need to update the pointer from A3 to now point to the most current value A2 and additionally we need to update the pointer of A2 to point to the older version of A1 which is the time travel example. So when you want to read an old version what you essentially have to do is you have to replay the deltas to put the tuple back into its original form. So in this case if we wanted to if we wanted to read A1 we would start with the value of A3 and then we would follow the pointer of A2, apply the delta in A2 and then apply the delta A1 and that would get us back to the original value, right? So this is another good example of the trade-offs between reads and writes so reading old versions and the append only approach is really easy which is one nice thing about it it's easy to implement, right? Because you just find the version and the tuple is already ready to be turned so in addition to being easy to implement you also don't have to put the tuple back together, you don't have to apply deltas to get it back to its correct state. But with delta storage, writes are going to be much faster because we don't have to copy the entire tuple if we only make a change to a subset of the attributes. So you know if you just have one attribute like we do here this is clearly a trivial optimization but in many tables you might have different versions of columns in which case this can matter a lot. But again, yes with the delta storage that is the benefit but the disadvantage is that you have to replay the deltas again to put the tuple back together into its correct value. So one take we can get from this is like we mentioned earlier Postgres Postgres will be faster for reads because well Postgres will be faster for reads and MySQL will be faster for writes for this exact reason. So the third thing that we need to know about on our list is garbage collection. So all of these old versions are accumulating as transactions are running and finishing and at some point we know that a particular version is not visible to any other active transactions. So what this means is if you're thinking about the table with the begin and end time stamps and the time stamp version it means that there are no active transactions with a time stamps that fit between that begin and end range from older versions. So at this point we want to go ahead and garbage collect these versions in order to reclaim space. So two additional things that we have to worry about are how we're going to look for expired versions and when it's safe to reclaim them. So these are topics that we're not going to cover in this class but they are covered in the advanced class if you do choose to take it. So there's two approaches that we're going to look at specifically the first one is tuple level garbage collection and the second one is the transaction level. So tuple level means that we're essentially going to do sequential scans on our tables and use the version time stamps and set of active transactions to figure out whether the version is expired. If it is then we go ahead and prune it. So the reason why this is actually complicated is because not only do we have to actually look at the pages in memory but we also need to look at the pages that we've swapped out to disk because again we want to vacuum everything right. So we'll go over vacuum background vacuuming and cooperative cleaning in the next slide. So the second approach is transaction level which we're really not going to go into much detail about but the general idea is that you have transactions that maintain their read write sets and you know when they commit so the versions are right so in this case you have the transactions again they're maintaining their rewrites read write sets so you know exactly when they commit and thus you can figure out when they're no longer visible and come vacuum them. So we'll first go over an example of how tuple level garbage collection works. So let's say we have two threads running in the system where so transaction T1 is assigned a time stamp of 12 and transaction T2 is assigned a time stamp of 25 and then over in our version table you can see we have object object A which is assigned version 100 has a begin time stamp of 1 and an end time stamp of 9 and then we have a few other versions in there for object B. So with background vacuuming what we're going to do is we have sort of a set of threads that run in the back room and they perform this vacuuming where they periodically just do a full table scan of the table and look for which versions are reclaimable and it works with any type of storage here so for background so here so you have a background thread that goes into the the goes to the transaction and it basically queries what the current transaction time stamps are so in this case it's going to be 12 and 25 then it's going to do a sequential scan on the table to figure out whether the tuples would ever be visible to them so would A100 be visible to them hard to say because we don't know yet but they're reading and writing but sorry let me back up so again sorry in this example we're just looking at the begin and time stamps here so here we gather the time stamps of 12 and 25 from these two transactions and then we again look at the beginning and end time stamp so they will never be able to use A100 or B100 because the time stamp does not fall between 1 and 9 whereas they do fall well the time stamp of transaction T1 falls between 10 and 20 so it could potentially use that value and at this point we know those two tuples are safe to reclaim so we go ahead and do so so one optimization here well one obvious optimization here that we can do is we can actually maintain a bitmap for dirty pages and so anytime you modify it you can just flip the bit of the page that you modified so again we're maintaining a bitmap for all of the pages in the database pages specifically if we modify a page we'll flip that particular bit which indicates that that page is dirty so this takes a little bit extra storage but it's just a single bit for all of the pages in the database and anytime you want it and so when the vacuumer comes around it immediately knows which pages it actually needs to vacuum right so it will go ahead and vacuum that page and then reset the bit to 0 so vacuum vacuuming again is typically ran as sort of a cron job that runs periodically but in some database systems for example Postgres you can actually invoke vacuum manually from the from the SQL prompt for example it also has configuration parameters that you can set such that the system will basically start up a vacuum thread if over 20% of the pages are dirty for example so there's different ways to implement this there's different ways to optimize it for different workloads okay so the other approach we're going to look at is cooperative cleaning right so and this is basically where the threads as they're executing queries when they come across old versions that they know are not visible to anybody else it's their job to actually clean them up as they go along so again these are these are threads that are actually executing transactions and they're going to actually check the versions that they traverse across whether those should be whether that space is ready to be reclaimed because they're not visible to any transactions anymore and if it is they will go ahead and reclaim that space so one thing to note is if you consider the two orderings that we discussed earlier oldest to newest and newest to oldest would this approach work for both of those no right why is that that's exactly right so in the case of newest to oldest you're not going to be looking at any of the old transactions so you will actually never end up reclaiming those so it's important to note that cooperative cleaning only works with oldest to newest ordering alright so now we'll just go through a similar example here so let's say that we have an index and transaction and one wants to do a lookup on object A now so it's going to again land on the head of the version chain which is the oldest value and then it's going to scan along until it figures out which versions are actually visible to it so if it recognizes a version that it's looking if it recognizes that one of the versions that it's currently traversing is not visible to any other transactions then we'll go ahead and mark them as deleted and reclaim the space and then at the very end of us also update the index to point to the new head of the version chain so we'll just go through these steps so here we find the value and so we can see that version A1 can be reclaimed and then we recreate the pointer from the index to the new version head so ordering is actually important here and the ordering that's actually done on the slide is not quite correct so when you actually perform these operations what you would do first is actually update so the first thing you would do is mark them as deleted but you're not actually reclaiming the space yet the next important thing is that you actually update the index pointer to point to A2 before physically deleting them or reclaiming that space because otherwise if you have other transactions running concurrently they might find an empty pointer that points to nothing yes so it's going to maintain some information so they can figure out so it's going to know the set of active transactions and be able to compare those time stamps with the begin and end time stamps that in the version table correct alright so again transaction level, garbage collection here we just maintain the read write sets of transactions and we use them to figure out what versions are not visible anymore and then reclaim the space and that's really all we're going to say about transaction level, garbage collection so any questions on garbage collection or anything else up until this point so now we're going to move on to our final topic design decision which is index management so as I mentioned before the primary key index is always going to point to the head of the version chain anytime we create a new version we have to update the version chain or we have to update well we have to update the index to point to the new head of the version chain so this gets tricky when updating the primary key because now it's actually possible that you could have two version chains for the same logical tuple the way you implement this is when you want to delete the primary when you want to update the primary key you do this as a delete followed by an insert of a new logical tuple and there's some bookkeeping you need to maintain and you also need to understand how and when to roll back when necessary but for secondary indexes this is actually more complicated and this will be what we'll talk a little bit more about so with secondary indexes the two approaches we use to make sure that our indexes reflect the correct value in the version chain are to maintain a logical pointer and here you have some kind of false identifier for the tuple or some kind of unique identifier for the tuple that does not change and then you have some layer of indirection an indirection layer that maps the logical ID to the physical location of the database and any time you update the version chain you just have to update the indirection layer rather than actually updating every single index right so the actual approach is I think it was used in some of the slides earlier I think which is to actually use physical pointers which is when you just point directly to the head of a new version chain so every time the version chain gets updated you have to update every single index right so the difference between the physical between using physical pointers and logical is you basically have this indirection table and the benefit of the indirection table is that you do not have to update every single index every time you update your version chain so alright so in this example we'll say we have a simple database and we're using a penda only version chain which is running newest to oldest right so for the primary key index if I want to do a look up on object A then this will just be a physical address right for the primary key which will be just a page ID so you know which page to go to and then you take the offset that's typically what this is it's going to point again to the head of the version chain right and anytime you create a new version you always update that with the primary key right alright so for secondary indexes again you could use the physical address but there's the same issue anytime you update the tuple you have to update the secondary index to point to this and you know this is again like similar to some of the sort of the delta storage idea that we saw a few slides ago yes if you have one attribute or if you have one index or one secondary index then this is not a big deal but it's very common for OLTP databases in particular to have many secondary indexes on a single table so every time you update the version chain you have to update all of those secondary indexes which for OLTP you can imagine might be 12 or a few dozen and this of course is expensive because for example if it's a B plus tree then you are traversing the B plus tree you're taking latches as you go and then finally you have to apply the update so again like we said in the previous slide instead of storing the physical address in the secondary index we're going to look at two alternatives so the first is to just store the primary key which is literally just a copy of the primary key as the value in the secondary index so this physical address there we go right so here we're going to have the actual value that we're going to store in the secondary index is going to be a pointer to the primary key index so now when you want to find a tuple you first get the primary key index out of the secondary index and then you do a look up on the primary key index just as you would to figure out what the physical address is and then everything proceeds as in the first example of the physical address so at this time I update the tuple and the head of the version chain you can just update the primary index and automatically updates all of the secondary indexes right so this is one example of logical pointers and this is what my sequel does and Postgres actually stores the physical address yes a secondary index see if your primary key index right which stores like the key for your immediate table so your secondary index is going to I guess be a reference to that key so yeah so in this case so like if you so if you have a table A and the ID is your primary key in table B you have a reference to table A dot ID right A the attribute column in that table and so you might create a second this is what's called a secondary index on that particular item so if you want to think about something more concrete you have a table of users your user has an ID your user has a list of items that it has purchased so for each of those items are the user's ID in it or it's just typically used for track any other questions I think I might be getting ahead of myself here so the last approach which is also another example of using a logical ID is basically you just have some synthetic value that's like a tuple ID so this would typically be an increment encounter to serve as the tuple ID and then you have a hash table that says how to map from that tuple ID to the address so so basically you're going to get the tuple ID out of the secondary index right so you're going to get the tuple ID out of the secondary index and then you're going to and then you're going to figure out where the physical address is and then the hash table here will point you to the location of the physical address so you can read that value and again similar to the approach we looked at where we were just storing the primary key index this is another example of logical pointers which means that each time we have a new version or each time we update the version chain we can actually avoid having to update all of the secondary index right so the only thing we have to update in this case is the hash table and the pointers does that make sense? alright so this table is actually really interesting so this is a table from a paper that was published by Andy and a few other students I think a couple years ago so what they actually did is they looked at a number of systems so they looked at some older systems like Oracle, Postgres and MySQL also looked at some much newer systems within the past 10 years so for example like Hyper and NeoDB, Hyper would be an example of an academic system so they tried to get a variety of systems here and the table lists which of these design decisions each of these database system makes so let's see if Andy has any exciting things so I guess he says the spoiler if you guys want the spoiler is that or the takeaway of the spoiler is that Oracle and MySQL the way they do MPC they actually found like Andy and some students actually found this way to be the fastest for all TP workloads specifically and they actually found Postgres to be the slowest although personally as both the user of MySQL and Postgres I like Postgres quite a bit but I'm also not running commercial database systems with production workload traces so once you get at that scale it probably matters well it definitely matters a lot so okay so this brings us to the conclusion so today again we talked about multi version concurrency control and again as you just saw in the past few slides a lot more to this than just figuring out what time stamps to assign and what versions are visible to the different transactions so of course you need to figure out how to store the versions, how to update them, how to update the indexes correctly and the other items that we covered here so right for next class just as a reminder don't come the class on Wednesday because nobody will be here so you guys have next Wednesday off and then I think the following week Andy will probably be back although that's not certain but we will start logging in recovery so so so so so so so so so so


Let's start. All right, welcome, everyone, to today's Webmaster Central Office Hours Hangouts. My name is John Mueller. I am a Webmaster Trends Analyst at Google in Switzerland. And part of what we do are these Office Hour Hangouts, where folks can join in and ask their questions around their website and web search.  But if any of you want to get started with the first question, jump on in now. Yeah, hi, John. Hi. I have a question regarding my eight months old website, actually. It was ranking very good until one month before. It was ranking very well. And it has a few backlinks also from nice websites, good websites. And that's why it was ranking well. But all of a sudden, my website got spammy backlinks from my competitor. My competitor created porn-related keyword backlinks all over the internet. And after that, all of a sudden, my website gone out from the search results. So what preventive measures I can take and how can I recover my rankings than how to proceed from the current situation? OK, so I think if your website is just, let's say, a couple of months old, maybe eight months, maybe a year, then that's still very, very fresh with regards to the rest of the internet. So that's kind of a time where our algorithms are still trying to figure out how and where we should show your website in the search results overall. So that's something where it would be normal to see some kind of fluctuations around how it's being shown in search. Sometimes things go up for a while. Sometimes they go down for a while. And then I'd say over the course of a year, things settle down in kind of a stable state. So that's something where I wouldn't necessarily worry too much about this particular situation. I'd continue working on your website and over time, that's something that should be reflected in search overall. Actually, my question is regarding spammy backlinks. My competitor has created 1,500 websites, backlink websites, created backlinks from 1,500 websites, different websites. And those keywords on those links are spammy, like, partner-related keywords. And I think that's the case. That's something that we see all the time. It's really easy for people to run a script and to drop thousands and millions of links on the internet. And we ignore that. That's something where people get really busy and they do all of this crazy stuff. But our algorithms have seen it so often, they're used to just ignoring it. But actually, that's not the thing I would worry about. But the anchor text doesn't matter on those spammy backlinks or not. If we ignore those links, it doesn't matter at all. It doesn't matter which websites. Whether it is follow or no follow. Whether it is do follow or no follow, doesn't matter. Yeah, no, no. This kind of thing is really easy, where you can take $5 and send it to someone and they'll put thousands of links up on the web. And people have been doing this for years and years and years. So should I take a preventive measure like disowing all those URLs? I don't think you need to. I don't think that would change anything. I would just completely ignore it. If your competitor is focused on building bad links for your website, then at least they're not making a better website for themselves. Yeah. Yeah, OK, thank you, John. Sure. Hi, John. I have a question. Hi, I'm Chris. So thank you for all the help with the webmaster community. So I think my colleague has joined the German webmaster yesterday. And thank you for being there, too. So my colleagues and IIG are facing some display issue for some of our pages in Google search. So basically, for many of our US.com products subscribe pages, Google is putting the metadata such as the metadata, meta-title, meta-description, and structured data for product pricing. But it's not putting it on the URL. So you can see the URL is .com. But we are seeing German and Finnish metadata on our US.com pages. So when we subscribe the URL for the US German and US.com pages in the Google Search Console, we just saw that the self-declared canonical is the German and also sometimes the Finnish pages. So when we look at our source code, for all the US German and Finnish pages, it's actually pointing to our own respective pages. So there's no issue with our HFN tag implementation. And I just have some quick questions here. So one question is, why is Google search showing the German and Finnish metadata on our pages? And also, is it possible that the Google bot is visiting our US site from non-US countries? Is so could the automatic redirect of the search bots be causing the incorrect caching? And finally, will it be acceptable? I mean, will it incur any penalty if we were to exclude the search bots for these Joe IP browser language redirects? As our intention is to serve the best page and language to the correct country users. OK. So I think that adds a little bit more flavor to what I heard yesterday. Yesterday, it really sounded like we were mixing things up across different languages and countries. Usually, when we mix things up with regards to internationalization, it's content that's in the same language for different countries, such as if you have the same German content for Germany and for Austria, then our systems might say, well, it's the same content. We can treat it as one page. But that wouldn't apply if it's German and Finnish and English kind of this kind of makes up. But what you kind of mentioned there is that you're doing some kind of an automatic redirect based on the location of the user. Yes. And sometimes that can be problematic because Googlebot crawls from one primary location for a website. And for the most part, that's probably going to be from the US. That means when we crawl your German pages, your Finnish pages, or whatever, we will crawl them from a US ID address. So if you're automatically redirecting US-based users from the German page to the English page, then we would think that you're trying to fold these pages together and that we should treat them as one page. So that might be something that's happening there. I think from a practical point of view, it's kind of hard to test unless you have the ability to test from different locations. One thing you could do is specifically for Googlebot is to use the Inspect URL tool in Search Console to see which version Googlebot sees when it tries to access the German version or the Finnish version. Maybe that makes it a little bit clearer with regards to what is happening on Google's side. The issue is for US site, when the Search Engine robots are visiting the German .e and .finish pages, they are not redirected. Only when they are in Germany, when they visit the .com pages, they are redirected. So I'm just curious whether, I mean, we are searching it from the US box perspective. There shouldn't be any redirect through the German and Finnish pages for our .com. OK, that sounds better. Yeah, so like I mentioned, we generally crawl just from one location for a website, and usually that's US. So it wouldn't be the case that we would from time to time crawl from Germany or crawl from other IP addresses. It is really, we do it all from the same region for each individual website. And for most websites, that's from the US. What I would do in a case like this is maybe send me some details of what exactly you're seeing, which URLs you're seeing, and which kind of queries you're seeing, the wrong language and country version. And then the site search for you in the chat. So this is the site that we are seeing. So we are seeing actually in the query, there is different version. But you can forget about the parameters. But we are seeing like the English version and also the Finnish and German language. But it's getting better. Like for now sometimes, when we search English query, we actually get the Finnish or German metadata. But for now, today, when we search, it's back to English. But it keeps alternating. So it actually affects the click-through rate for our English users. So what we have thought is, is it all right if we as code Googlebot from the redirect, is there any penalty from our app if we do that? Because what we did is we just want the user to go to the correct version for maybe in Germany. But maybe for the US bot, if they're having problem to display correctly, we can just exclude them from the redirect. I don't think we would see the redirect. Because if you're not redirecting users from the US, then we wouldn't see what you're doing with German users anyway. So that should be something where I don't think it would change anything if you explicitly excluded Googlebot from that redirect. But I'll take a look at the sample that you have there and see if there is anything specific that you can change. Or maybe there's something on our side that we're picking up wrong. Because sometimes it also happens that we pick something up wrong. Yeah, sure. Thanks for that. OK, let me run through some of the submitted questions. And if you all have any comments or questions along the way, feel free to jump in as well. And probably towards the end, we'll have some more time to chat as well. So the first one is about mobile-first indexing. There are websites out there that are mainly used from desktop devices. And the question has a little bit more detail, some ideas about that. And the question is, will mobile-first indexing hurt those websites? They might still be responsive and everything. But maybe they're seeing by Google is not really working great on mobile devices as on desktop. So from a practical point of view, with mobile-first indexing, it's about indexing for us primarily. That means we need to be able to see the content on mobile devices. And if the functionality is slightly different, but the content is the same or the content is what you want to have indexed, then that's all OK. Then you're pretty much set for that. So with that in mind, even if your website is primarily used by desktop users, once we switch to mobile-first indexing, we will index it like a mobile user. And it's not that it will be shown less frequently to desktop users or less frequently to mobile users. It's just we use a mobile version for indexing, for determining what you want to have shown in the search results. So that's something where websites where I would say they're essentially desktop only, like the really old school websites that are built with a tables layout that are not responsive design. Where when you access them with a mobile device, you have to kind of zoom in and try to find all of the content that way. Those are websites that work really well on mobile-first indexing because all of the content is exactly the same on desktop and on mobile. And the display is slightly different, but the content is essentially the same. So those work really well for mobile-first indexing. What we'll kind of play into this a little bit, I think, is once we start using page experience as a ranking factor, within page experience we do have mobile friendliness as a ranking factor as well. So if a website is not mobile-friendly, then maybe that's something that will play a role in kind of the ranking of that website overall. But page experience is something that we've essentially just announced our intent to go down that direction and we'll let you know at least six months before we start using it as a ranking factor. So that's something where you still have a bit of time to try to figure out what really makes sense for your website. The next one is also about mobile-first indexing. We're trying to be prepared as possible for mobile-first indexing switch that's happening in September. How much can we rely on lighthouses SEO mobile results as an indication of what to expect when the switchover happens? So this is kind of a common point of confusion with regards to mobile-first indexing. It's not about mobile friendliness. It's really about mobile indexing. So if you're using Lighthouse to test how mobile-friendly a website is, then that wouldn't necessarily reflect what we would use for indexing. If it's a responsive website where the content is essentially the same, the presentation is very similar, then that's something where probably we will just be able to work with that right away. If you show different content from desktop and mobile or if the responsive design is very different on desktop and mobile, then that's something where maybe you would see changes with regards to mobile-first indexing. So with regards to the way the content is presented, one of the things that I feel people haven't really focused on too much, or where we still see problems at least, is that if you have images or videos on your pages and they're very prominent on the desktop version and on mobile, they're very small, very tiny, in a corner or on the bottom of the page, then with regards to image search and video search, those are less likely to begin good landing pages for images and videos, right? Because the user is trying to search for an image. They find the image in the search results. They click on the page, and then they can't find the image on the page, then that's a really bad experience. So if you care about image search or about video search and you have a website that's switching over to mobile-first indexing, then it's really worthwhile to make sure that your image and video landing pages are really such that the content that you want to be found for is very prominent on those pages. Then a question about Core Web Vitals. There are custom fonts on a page that need to be loaded. It's recommended to use font display swap because it will show the text to the user as fast as possible. Now with Core Web Vitals, it's recommended to use font display optional because we don't want to shake our page when swapping the fonts or where we get a bad CLS score. To be honest, I don't have any experience with regard to that, so I don't really feel qualified to say which exact attribute you should be using for your custom fonts there. What I would recommend doing is maybe pinging us on Twitter, and we'll try to find someone for you that can help you to figure out what the optimal approach here is. Does Google use links as a part of geotargeting and determining the location of a website? From what I've seen, what I've been seeing, geotargeting takes a bit of time before we start ranking in major countries, such as the US or the UK or even Russia. We start ranking in little or non-spam countries with a low population. It's very confusing. So we use links in lots of places around Search. I don't know if we would particularly use that for geotargeting. But in general, with regards to geotargeting, you can tell us the preferred geotargeting of your website, either by using a country code top local domain, where you can essentially tell us right away what the geotargeting is that you want, or by using the geotargeting setting in Search Console. And those are really the primary ways of letting us know which countries you want to target. And all of these more exotic signals that we have to pick up are more for the situations where we don't have good information about a website. So that also includes things like the IP location of the server. If nobody tells us where this website should be geotargeted and we think it should probably be geotargeted, then sometimes the IP address of the server helps us. But if we already have other information for geotargeting, then we don't need kind of those small details as well. With regards to the time it takes for ranking, I think it's completely normal that if you start with a website, then you probably end up ranking first in areas where maybe there's a little bit less competition, where it's a little bit easier to get started. Whoops, let's see. Bit of noise in the background. Cool. We have a website version for the US. However, we're not able to display the same content for all US states. Is there a way that we can tell Google to send us visitors or just targeting only for certain states? If not, how does Google handle the fact that the users from some states are very satisfied with our content, but others from the states were not able to display the content and set up their queries or not? Is Google able to see which states users come from? And depending on that, adjust our ranking for only certain states. So I think, first of all, we kind of have that situation that I mentioned before with the other international sites in that we primarily call from one location. So if you're changing the content for different regions within a country, then probably we would not ever see that. So if you're doing that on a state-by-state basis or on a city basis, we would never really see that. We would probably see the content that is mapped to, I don't know, California, Mountain View, or wherever. It's a bit weird with IP addresses that come from data centers because they end up being shared across the different data centers, and you just assign them to one arbitrary location. So that's something where we would probably just see the version from one location. So that makes it a little bit tricky with regards to swapping out the content for different locations. Usually what I recommend in a case like this is to have a home page where you have some part that is customized by location and some part that is just general for your home page so that when we crawl that home page, we have enough general content to rank your website for. And the more customized content for individual location links out to different versions. So you would have a link to maybe a version for California or a link for Alabama or whatever. And we'd be able to find those links anyway. So we can crawl all of those city or state-specific pieces of content, and we can index them individually so that if someone is searching for whatever your business does plus that state, then it would be easy for us to map that and say, well, actually, this is the piece of content that probably matches what you're looking for. So that's kind of the direction I would head there. With regards to Google automatically figuring that out, sometimes we can't figure it out, sometimes that's a bit trickier. It depends a lot on how easily we can understand what the user's intent is. Is it that they really need something local? And if so, then maybe their location should be a factor that plays a strong role in the query. Maybe it's something where we don't know if the user is looking for something really local. Then maybe we wouldn't know to pick that local version of your page and rather we would pick a generic version or maybe a different location version of that page. Because this is something that is kind of, I don't know. I think we're getting pretty good at it, but it's still kind of hit and miss. It's something where my general recommendation there for international sites, but especially for sites where you're customizing the content by subparts of a country, is to try to recognize the location of the user. And if you can recognize that they're accessing a page that is not the best one for their location, then show a little banner on top so that the user can go to the better version. But they can still access that individual version. By letting the user still access that individual version, we don't have any problems with indexing because we can access all of these different country versions or city or state versions from our crawler in California because we can still access that content. But for users, when they go to that page and they go to the wrong version, they have a little banner on top telling them, hey, actually, there's a better version for you. Probably check it out here. So that's kind of the recommendations that I would have there. When people use Google Gmail Instant Login or sign up and it redirects users away from our website to a Google login interface and then redirects back to our website after logging in, does Google understand that they're not bouncing?  The same for Facebook login redirects. So I think there's a bit of misconception here that we're looking at things like the analytics bounce rate when it comes to ranking websites. And that's definitely not the case. So if you have content on your website that is accessible to users once they log in, then using these kind of login providers, I think is a really good thing. From a security point of view, from what I hear from the security teams, this is actually a lot better than if you implement your own login scheme for most websites. Because creating a good and secure login system is surprisingly hard. So my recommendation would be to continue using things like this. And if you're using analytics to track it yourself, then obviously you need to figure out how you want to track that. But it's not something that I would worry about from an SEO point of view. The only aspect from an SEO point of view that kind of comes into play with these kinds of sites sometimes is that, obviously, Googlebot is not going to be logging in to your website. So if there's content that's only accessible after login, we would not be able to index it. So that's kind of the main aspect with regard to these kind of sites that's worth keeping in mind. My rank was number one, for most words. And the impressions on my site increased from 200,000 to 300,000 a day. But there was no change in the clicks. And the next day, my impressions dropped back to 200,000. And my clicks were the same. What could be the reason for that? It's really hard to say. So this is the kind of thing where I would recommend going to the Webmaster Help Forum and giving some of the details of what it is that you've been seeing. Because probably there are very simple explanations for this. But it's worthwhile to kind of talk with other people who have seen similar things. It might be something as simple as, I don't know, maybe an image was being shown from your website instead of a normal text listing. These things can sometimes result in the impressions going up really high. It might be that suddenly people are searching a lot more for your website. Or it could be that your website kind of went from the first entry on page two to the last entry on page one. And suddenly the number of impressions went up significantly. But maybe it's still the case that people are not clicking all the way down to see your site in the search results. So there are lots of these subtle things. But it's worth chatting with other people who have looked at this kind of data before. And showing a bit more about the things that you've been seeing, like which URLs, which kind of queries, what numbers you're actually looking at there. I'm doing a 301 redirect from a subdirectory on my site to a subdirectory on a new domain. Once they're redirected, I will be displaying a pop-up to inform users that they have been redirected to this new page. And once they read it, they can click Continue to move on. Would that affect anything? No, that would not affect anything from an SEO point of view. Because from an SEO point of view, we would see that redirect. We would follow that redirect. But we would not be sending any refer information for all of the requests that we make to those pages. So purely from an indexing point of view, we would probably never see that pop-up. So we would be able to index the new content right away. We'd be able to follow the redirect forward the signals to the new page. And all of that would essentially just continue to work well. I don't know how well this works for your users, but ultimately, that's something between you and your users where you probably want to make sure that you're not getting too much in the way, but that you're informing them appropriately if that's something that you're trying to do then. I work on a site with separate mobile URLs. And recently, it switched to mobile-first indexing. How would a page benefit in any way from getting external links to m.example.com rather than the desktop URL? Have you ever tested? Or can you speculate what would happen if the canonical became the m.version on both versions and the real alternate added to the mobile version pointing to the desktop version? So with separate mobile URLs, or when we switch to mobile-first indexing, in general, with separate mobile URLs, even before mobile-first indexing, we take the m.version and the desktop version, and we fold them together as one page, essentially for indexing purposes. So any signals that go to either of these versions would be combined and focused on one version. Before mobile-first indexing, they would be combined on the desktop version. With mobile-first indexing, they would be combined on the mobile version. And what will happen from a practical point of view is, internally, we will pick the m.version as the canonical URL. That's the one we'll use for indexing. And we'll see the desktop version as kind of an alternate URL for this web page. So when someone on desktop is searching, we will know instead of ranking this mobile URL, we should be showing the desktop URL, that kind of thing. So internally, we would be picking the m.version as a canonical and kind of working from there. However, externally, from your side, you should be treating things as they were before. So that's kind of a bit confusing there, in the sense that you should continue to have the link rel canonical from the mobile version to the desktop version. You should have the link rel alternate from the desktop to the mobile version. The main reason we decided to keep that is because we're using this set of connections to recognize that these pages belong together and to recognize which one is the mobile, which one is the desktop version, and to keep it such that you don't need to watch out for when we switch to mobile first indexing, and then suddenly you have to change your whole website around. So we prefer that you keep kind of the normal connection between mobile and desktop with the kind of canonical pointing to the desktop version and the alternate to the mobile version, even if internally, we treat it the other way around for indexing purposes. So that's sometimes a bit confusing if you look at the details a bit too far. But essentially, our goal here is to make it so that you don't have to make any changes, but rather that we try to work out the changes on our side. And I guess just to be really clear with the first question with regards to getting external links to the MDOT version, that wouldn't change anything at all. So with mobile first indexing, without mobile first indexing, we combine all of those signals. It doesn't make sense to do any kind of separate work to promote your MDOT version over your desktop version or vice versa. It's essentially we combine all of those signals. An author on a prominent industry news site recently wrote that the rel canonical tag doesn't consolidate external link signals to the canonicalized page among a group of duplicates in a situation. Wow, this is complicated. In a situation where external links point at each of the pages in that group of duplicates. So I haven't taken a look at this article, so it's really hard for me to say what exactly was written in that article. But with the rel canonical, what happens there is we essentially use this as a signal for canonicalization. And for that, we need two steps. So on the one hand, we need to be able to recognize that these pages should be treated as one group. And we can do that by looking at the content, by looking at the pages. Sometimes we can recognize it in the URL if there are URL parameters that we can drop. Those kind of things, we also look at the rel canonical. So all of these things kind of come together. And then as a first step, we say this set of pages should be treated as a group. We should pick one of these pages from that group and treat it as the canonical URL. And then the second step is picking the canonical. And for picking the canonical, we use a number of signals as well. I think we have these documented in the Help Center somewhere, so things like 301 redirects. The rel canonical definitely helps us here. Internal and external links, things like site map files, hreflang links, all of these kind of extra annotations where you tell us a little bit more which of these URLs you actually want to have indexed. And we take all of these signals together and we try to weigh them appropriately. And we try to pick the right URL to show from this group of URLs that we think are essentially the same thing. So that's essentially what happens there. And in the situation where we put all of these pages into the same group and the rel canonical is one of the signals that aligns with the preferred URL that you want to have shown, then essentially all of the signals that go to any of the pages in this group, they're concentrated and focused on that one canonical URL. So that includes things like external links. That includes any other signals that we have for that page, also internal links. Everything is kind of combined into that one single URL. But depending on the situation, us recognizing that specific pages should be a part of this set of pages that we group together, that's something that might be kind of tricky if the content is very different, for example. And also with regards to selecting the canonical URL from that group of pages, that's also sometimes a bit tricky. That sounds easy, but it's not that easy to do in practice. And it's something where we I would say every couple of days we email a team that works on canonicalization and ask them, why did you pick this one instead of that one? Because people just have so many unique configurations on the web where our systems have to deal with the whole web. And sometimes we pick things in ways that don't make a lot of sense to humans when they look at these pages. Let's see. Question about content length and schema structures. Imagine a website that's presenting a feature about a specific topic. Along with the feature, there is a schema markup FAQ or how to section. Is the word count of these additional sections taken into account for determining the word count of the feature? Or is the length of the feature just determined by the feature itself without the FAQ or how-to sections? So I think maybe as a general comment, it's very easy to focus on word count on a page. And it's very easy to focus too much on word count on a page. So from our point of view, we don't use word count as a ranking factor. It's not that you have to hit a specific word count, and then suddenly your page is deemed as high quality. Sometimes really short pages are really good for users. They perform really well. Sometimes really long pages are what users are looking for. That's something where you kind of have to find that balance yourself. It's not that from our point of view, we would say, you need hit 1,000 words or 5,000 words. That's really kind of an arbitrary judgment that I think doesn't apply in a lot of situations. So when I tend to see questions coming in where people are saying, my high quality page has 4,500 words on it, you should be ranking it better, then my first thought is maybe you're focusing too much on the number of words on the page rather than the quality of the content that you're providing there. So that's kind of my thought here maybe as well in that it's very easy to count the words on a page and to say this is so important because I have 2,000 words on this page. But actually, our algorithms don't look at the number of words. So you kind of have to take a step back and think about the page overall. And with regards to different structured data elements, it's the same thing. It's not that the word count matters. It's really that the value that you're providing is what's important here. That said, with regards to FAQ and how to, and maybe some other kinds of structured data that are not 100% sure of which ones might also apply, maybe special announcement would be similar, it is something where we need to have enough text to show in this kind of rich result box for a page for us to actually show it. So if you have a FAQ section and the question is why and the answer is because then probably our algorithms are going to say, well, this is not very useful. Maybe you should kind of elaborate a little bit more before we start showing this in the search results. So that's something where maybe you'd want to look at the size of your questions and answers just to make sure that it kind of aligns with what would be shown in the search results. But otherwise, I really wouldn't worry about kind of the word count of a page. Some websites use different approaches. User behavior for desktop, mobile on AMP, like on Mweb, browsing using layered approach. You click on a page, a page layer opens with less content compared to the web version on desktop, a regular click to URL with a redirect to regular web page and on AMP. You click on a URL, since AMP doesn't give you flexibility to do so. Will this come under good or recommended practices? I don't know how much it makes sense to do such vastly different approaches on different devices. So that's something where I would try to be a bit thoughtful on what it is that you're trying to do there, rather than just doing whatever you can do with regards to your technology. It's very easy to kind of similar with word count to focus on a technology and say, well, I can do all of these crazy things. Therefore, I will do them, and it looks really fancy. But is that really what works best for users? I don't know. Maybe it is. Maybe it works well for your users. With regards to the different versions on different pages, the thing to keep in mind is with mobile-first indexing, we will be indexing the mobile version of the page. So if the mobile version of your page does not use normal URLs for navigation, then we will have trouble indexing your mobile site because we won't be able to access those non-urls to get to the content. So if the whole navigation on the mobile site is really purely JavaScript-based, you're swapping out different layers on a page, it stays on the same URL, there are no actual links on this page, then we would probably have a lot of trouble being able to crawl and index that site. And probably we would not shift that site to mobile-first indexing at the moment. But at some point, we're going to kind of make the decision and say, well, we need to shift everyone over. And that will mean we'll shift your site over as well, even if it's not ready yet for mobile-first indexing. And if really all of the content on your mobile site is not accessible through normal URLs, then we will drop that from the index. So that content won't be shown in the search results at all. And with mobile-first indexing, it doesn't mean that it'll be dropped for mobile users. It'll be dropped for desktop users as well. So if that content is not accessible on mobile, we will not be able to index it. With regards to AMP and mobile and desktop, we treat AMP pages as being alternate by default. So we wouldn't use the AMP page for indexing. There are certainly ways that you can set up a website so that the AMP page is your mobile page, and you have an alternate desktop page where you just have a desktop version and the AMP version. And in a case like that, we would see the AMP page as being a normal mobile page, and we will just index that normally. The other thing that kind of plays into this complex scenario of mobile desktop and AMP is that when it comes to the page experience score, kind of the core web vitals where we're testing the speed and stability, usability of a web page, we will test the version that users end up seeing. So that means we would test the AMP version with regards to speed and kind of the quality usability. From that point of view, we would not test the mobile version for that. So that's something where in this situation, with mobile-first indexing, we would index the mobile version. We would use the AMP version with regards to testing usability and speed, and we would show the desktop version in the search results as an alternate URL when people on desktop are searching, but we would not index the desktop version. So it gets really complicated. My recommendation for this kind of situation is to try to simplify things as much as possible for your website. And instead of having three different variations of the same page, find a way that you can use some kind of responsive design so that you either just have two versions, maybe kind of like desktop mobile combined and the AMP version, or maybe there's even a way to move to a pure AMP framework where you essentially use AMP for the whole website, because AMP is a responsive web framework, so you could theoretically do that for a lot of things as well. John, a question on that. Do you think then, or is it the websites that haven't yet shifted to mobile-first indexing? Are websites that need to do something about that? Will you be notifying websites that need to do something about that in upcoming months? Yeah, we've been notifying sites for a while now with regards to the bigger issues that we've noticed. So that's something where I expect us to continue doing that. With regards to mobile-first indexing, we recently did a review with the mobile-first indexing team. And it seems that most of the sites that are remaining kind of fall into two buckets. On the one hand, the sites that basically don't make any changes at all, which are probably a lot of sites that are either just created once and then kind of left, or maybe sites that are just kind of, I don't know, gone stale over the years. That's kind of one big bucket. And the other bucket is really large websites that have complicated setups. Maybe that's something similar to your website that you're working on there. And that's something where we're looking into ways to make it easier for us to notify them of specific issues that we're still seeing there. Great, thanks. I just had another further question. It was about we've seen some changes over the last few months. So since April, Googlebot's slowing down its crawl by about 40%. And this is across all of our classified sites. And is that something that's a global initiative that you guys are working on, or is it something site specific? Probably more site specific. So I'm not aware of us slowing down crawling in general. I think that would be kind of tricky, because the web is still growing. Content is still coming and going. Maybe it's just that we're focusing our crawling a little bit differently in between. But in general, we should continue to be crawling normally. Hey, John. Hi. How are you doing? You're doing great today, right? Pretty good. All right, good to you. John, I have a question about regarding the core web viral. Using a page as a ranking factor, it means you need to be able to have in the user data to be able to tell these pages fast, these pages slow. Is that right? So when a page doesn't have a significant amount of traffic, how does it handle in this scenario? Yeah. So for the core web vitals, we do show a kind of in-search console and in-page speed insights if we have enough data from the Chrome user experience report. So that's something where if a website really has a low amount of traffic, then we wouldn't be able to show anything there, and we wouldn't be able to take that into account. But that's something that's very similar to other kind of ranking factors that we have. For example, if a website is really new, then we don't have a lot of kind of historical data about the website, and we kind of have to guess. So that's something where from our point of view, we would be able to take this situation and still say we don't have any speed data about this website. Maybe it's a completely new website. Maybe it's something where there's just not a lot of traffic to this website, but we still have to rank it somehow in search. So it's not that we would remove it completely from search. We would just say, well, for this particular ranking factor, we don't know. We have to make some assumptions, but we will try to compare it to other websites anyway. This is all right. Thanks. Yeah. So I wouldn't worry about it if it's just that you don't have a lot of traffic yet. If you're working on your website then over time, probably you will have a bit more traffic. So hopefully that kind of settles down, but it's not something where we would say, well, we would never be able to show this website in search. So it makes traffic in the ranking factor in the scenario. We could say that. No. I don't think that would be safe to say, because it's really just about us having some amount of data. It's kind of like saying, well, age is a ranking factor, because if a website is completely new, Google doesn't know how to rank it. Therefore, it's not old enough to rank. But we have to deal with these kind of situations where we don't have data all the time. There are lots of ranking signals that we have where we just don't know for individual websites. And we kind of have to guess. And especially with new websites, people see it in different ways. So some people talk about kind of the honeymoon period where Google is ranking my website very highly, because it's a new website. And other people talk about the sandbox where it's like, well, my website is new, and Google is not ranking my website at all. All of these situations fall into the general bucket of, well, we don't have data for this website, for this particular scenario yet. So we have to make some assumptions. And we will see if those assumptions were OK. Hi, John. Hi. Hi. So my question is related to Google Search. So what I have noticed recently is that if you put the title and the date, the content is ranking on the top in featured snippet, like for keywords like, let's say, that phones under 10,000, phones under mobile phones under 15,000. If you look at the top ranking keyword, what the sites are doing is that they are just manipulating the date every day, every 24 hours. And these things are coming on featured snippet. But if you look at the content, it's hardly anything new. It's just the date is changing every 24 hours. So is it a ranking factor, or is it a bug, or what is your take on that? It's hard to say without looking at some examples there. It could be that it's something that we should be able to improve. What I also notice with a lot of queries is that it's very easy for a site owner to get fixated on one specific query and to start seeing problems there. But when we look at that on our side, we see, well, 10 people search for this query last month. And then from our point of view, it comes across as something, well, maybe we don't need to spend a lot of engineering time to improve this particular query or this particular kind of query, because it's just so rarely used. It's something that a site owner would use when they're copying, pasting their titles or when they're explicitly checking something to see if a competitor is ranking for something exact. Then you might see that. You might look at it and say, well, it looks really bad. And Google is getting misled by this kind of guy who's trying to manipulate the search results. But if you're the only person who is seeing this, essentially, maybe a handful of other people, then maybe that's not something that you need to worry about. And maybe that's something that our engineers don't need to worry about. But it can also be that it's affecting a query that is very visible and where we should be doing a lot better. So if you can give us some of those details, that would be fantastic. You could drop them here in the chat. I'm happy to pick them up and pass them on to the team. I think someone has already posted on the chat, John. I just see someone by name on digital. He has already given some examples, I guess. So I just read his thing. And it's happening in research in India. So I just noticed it. So I thought I'd just ask him. Thanks, John. Sure, I mean, I'm happy to take a look at these things. I always get to transcript afterwards. So it makes it a little bit easier to double check with the teams on that. Cool. OK, let me pause the recording here. If any of you want to stick around and kind of chat a little bit longer, you're welcome to do that. But just for sakes of having a reasonable cutoff for the recording, thank you all for joining in. Thanks for all of the questions that you submitted. It's always good to see a bunch of new faces as well, and wishing you all a great weekend, and maybe see some of you one of them future times as well. Bye, everyone.


What's good charge boy Ross back again with another video So I've been wanting to talk about this video in especially what happened on this week's SmackDown Dominic came out there with the rest of judgment day, and I'm not gonna lie to you the reaction Dominic got before he could say any word Was just amazing The nuclear heel heat He was getting Reminded me of the time when Roman Reigns had beat the undertaker and it was the raw after WrestleMania And he couldn't even get a word in for about ten minutes straight. That was the same Type of feeling I was getting reaction wise from that crowd Dominic couldn't say a single word on this week's SmackDown and that was Fantastic, I want you to understand the comparison of where Dominic was When he was teaming up with his father during the pandemic era and stuff like that To where he is now and I wanted to talk about this video because his growth Character-wise in ring-wise confidence on the microphone. It's great And I hope they continue that When Dominic came in it was a good field moment because we hadn't seen Dominic in so long On a WWE television. So to see him with his father and and they're doing their tag team thing You know, it was a good field moment initially But Dominic didn't really have any personality like all people saw him as is raised son That's just what it was. And it was cool for a little bit But you didn't really you didn't get that sense of personality from him Hit the most noticeable moment is when he was getting torn up by them Kendo sticks by By Seth Rollins or what now he was getting tore up when Seth Rollins was feuding with Ray And then another noticeable moment is when Dominic was thrown It was during the pandemic era. He was getting he got thrown out the ring by Roman Reigns because Ray was feuding with Roman Reigns at the time So and in another noticeable moments when he was getting beat up by Brock Lesnar. It's like that was Dominic's Noticable moments when he was teaming with his dad when he was aligned with his dad was him getting beat up Now is it his in-ring moves were kind of still rusty kind of we're not rusty But they were you can tell he's very green He didn't seem fluid and smooth in the ring and of course that's gonna take time You know, but at the same time you knew he was trying, you know He was getting that rub because of his father and there's nothing wrong with that But no one cared people love Ray people love Ray Ray is Goated it's just no one really cared about Dominic and when they turned them heel and when he turned on his father And aligned himself with the judgment day That's when things took off to the point Where they have been building this has been a slow build Ray has been refusing to put his hands on his son, but Dominic's been very Disrespectful at every chance it even got to the point where Ray moved to smack down because he just Didn't want to do this with his son anymore on rock The harassment of disrespect. He just couldn't take it no more. So he moved to another brand only for Dominic to come to that brand and cause some more chaos right before WrestleMania and it was so Good how they slow built this because Dominic just kept going kept going kept going He kept being annoying. He kept being disrespectful to his dad and what works is They're playing to his strengths He's not the best in the ring. He's still trying to get it together and that will take time But they're playing to his strengths. He's feeding off the other group members in judgment day. They have his back.  That's exactly what he is and the great thing about those type of heels is They will do whatever it takes to win They will sit up there and and when they're in a disadvantage or in a situation where they look like they're about to lose They'll plead they'll beg and then someone will bail them out hence judgment day they'll bail him out and then when he gets this this Horrible victory horrible win that he didn't earn.   He's not all there yet in the ring.  He'll talk trash when he's winning But when he's losing he backs away That's perfect. It fits him perfectly and ever since they turned them heel and they've just been doing this slow build with him and his father It's been fantastic At one point in my opinion and I think it's starting to change as a late He was definitely one of the top heels in the company because he's been consistently been getting that reaction Since he's turned heel. It's just been amplified even more and then you got Michael Cole Who's going in on him on commentary like he despises him? He is literally the voice of everyone at home and it works So this past week on SmackDown That reaction he got those type of boost and he's been getting those type of booze He got that type of reaction at WrestleMania Great match with his father. He didn't end up winning But he's the one person that people I think will pay to see get beat up And the reaction he got this Friday night was Fantastic, like I said, I haven't heard that type of reaction that type of heel heat From from a crowd since like Roman Reigns defeated the Undertaker in that Monday night raw after it was great It was great Honestly Honestly, he got more heel heat than Roman got when he came out there on this week's Monday night raw because there's still people That love Romans. There's still people that that put the ones up for Roman So in my opinion, I said it on the live stream. I think he's the number one heel in the company I honestly do think Dominic Mysterio is crazy to say this in 2023 He is the number one heel in WWE. I'm actually trying to think is there any heel that's bigger than him I don't know Maybe well, no, I can't even say Brock because people still like Brock even though he destroyed Cody, you know, but honestly, I Think it's Dominic, bro. He gets that no one's cheering for him People would cheer for Brock here and there people will definitely cheer for a Roman You know, sometimes people, you know, you know solo is a good heel. He doesn't really say much But I think that's just my association. I don't think he gets those type of booze You know, he's more of like an enforcer if I if I have to be honest, I Think Dominic may be the best heel in WWE right now The reaction he constant he doesn't get mixed reaction is straight when he comes out He talks on the microphone is nothing but booze. No one cares to hear him and people love that People love to hate Dominic and I think that's a perfect thing that they got lined up here So, yeah, man, it's great to see Dominic come from where he was with his father with the baby face gimmick to where he is now He is starting to become his own man. He's not oh, that's just Ray's son. No, he's Dominic now He is embrace the the him being a Harden criminal. He's embraced judgment day. He is if outside of real Dominic is probably the best part of judgment day. It's real and Dominic they make Judgment day what it is they give judgment day that extra heel factor real people like her So they're gonna cheer her, you know, don't cheer her but boo her when they need to Dominic Nobody likes him in the crowd Everyone wants to boo him and it's great It is fantastic if you can get a little bit better in the ring Which I do think time will tell and he's got he's gotten more confident on the microphone. I Think honestly, I think we may have something big here It just depends on how they continue to book him. They need to continue this He needs to stay where he is right now because he is doing WWE doesn't really have a big top heel. He's their biggest heel in the company without a doubt. There's no There's no after especially after last Smackdowns that whole segment on Smackdown. There's no denying it. So comment down below. Let me know. Are you guys enjoying? Dominic's heel work his heel run. Are you guys enjoying it? What what else would you like to see more from Dominic? Do you think he should become a mid-card champion sometime this year? Let me know down below, but I appreciate all love and support you guys have shown on channel road to 150k And I am still your undisputed YouTube res on champion world. Appreciate y'all kicking me. See y'all next one. Peace


If you choose to go with us, you know, this is more of the quality of follow me. I'm calling you out of the world stuff. This isn't your typical seminar or workshop. It's like saying that if you become God-dependent and you give yourself so over to your intuition, I mean like 100%, or the Holy Spirit, or higher power, or Atman, or whatever you want to call it. It doesn't really matter the name that you use for spirit. But if you give yourself over fully to spirit, and I mean immerse so deeply that you're willing to let go of your everyday ordinary perception of the world and your everyday ordinary perception of yourself in the world, then that's where these miraculous experiences come. Not every once in a while, not like a little glimpse here or there, but they actually are quite consistent in your awareness. But you can hold on to nothing. As he says in Lesson 189, you know, simply do this, be still. Lay aside all the thoughts of what you are or what God is. Hold on to nothing. Do not bring with you one thought the past has taught, or one belief that you ever learned before from anything. So oftentimes too, of course miracles is thought to be a tool, just one among many, many really amazing tools on the planet. Only one pathway in the universal curriculum among many. But they're all designed to take you into a mystical experience. It shows you and reveals to you who you are in God, in the source, in spirit.  You may think you're pretty good at financial management. You may think you know how to maintain the health of the body. You may think you know something about diet. You may think you know something about energy and polarities and balance and equilibrium and all kinds of things that you've learned through religion or spirituality. And if you go deep enough, all of those will get burned away too. I'll guarantee you everything you believe right now about spirituality will just go bye-bye.