Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Backend to Frontend: When database optimization affects the full stack

3,259 views

Published on

OFFSET it the root of all evil: It's slow and actually delivers the wrong result. OFFSET is just not the right answer to implement pagination. There is a better approach, called Key-Set Pagination, that is superior in many regards. However, introducing it to your application affects the full technology stack up to "Layer 8": The User.

Published in: Technology

Backend to Frontend: When database optimization affects the full stack

  1. 1. © 2015 by Markus Winand iStockPhoto/Mitshu From Backend to Frontend When database optimization affects the full stack @MarkusWinand @SQLPerfTips @ModernSQL
  2. 2. © 2015 by Markus Winand Full Stack, Really?
  3. 3. © 2015 by Markus Winand Full Stack, Really?
  4. 4. © 2015 by Markus Winand What Users Want are Used to
  5. 5. © 2015 by Markus Winand What Users Want are Used to Let’s click here
  6. 6. © 2015 by Markus Winand User Clicks on Page 2 Gimme Page 2! Gimme Rows 11 to 20
  7. 7. SQL for “Gimme Rows 11 to 20” se!e"# * $%om news whe%e #op&" ' 1234 o%de% b( da#e des", &d des" o!!se" 10 #$m$" 10
  8. 8. Inside the Database: Worst Case L&m&# (a"#ua! %ows'10) -> So%# (a%"ua# &ows'20) So%# Me#hod: "op-N heapso&" Memo&(: 19)B -> B&#map Heap S"an (a"#ua! %ows'10000) Re"he") *ond: (#op&" ' 1234) -> B&#map Index S"an (a"#ua! %ows'10000) Index *ond: (#op&" ' 1234)
  9. 9. Inside the Database: Worst Case L&m&# (a"#ua! %ows'10) -> So%# (a%"ua# &ows'30) So%# Me#hod: "op-N heapso&" Memo&(: 20)B -> B&#map Heap S"an (a"#ua! %ows'10000) Re"he") *ond: (#op&" ' 1234) -> B&#map Index S"an (a"#ua! %ows'10000) Index *ond: (#op&" ' 1234)
  10. 10. Inside the Database: Worst Case L&m&# (a"#ua! %ows'10) -> So%# (a%"ua# &ows'40) So%# Me#hod: "op-N heapso&" Memo&(: 22)B -> B&#map Heap S"an (a"#ua! %ows'10000) Re"he") *ond: (#op&" ' 1234) -> B&#map Index S"an (a"#ua! %ows'10000) Index *ond: (#op&" ' 1234)
  11. 11. Inside the Database: Worst Case L&m&# (a"#ua! %ows'10) -> So%# (a%"ua# &ows'10000) So%# Me#hod: ex"e&na# me&*e D$s): 1200)B -> B&#map Heap S"an (a"#ua! %ows'10000) Re"he") *ond: (#op&" ' 1234) -> B&#map Index S"an (a"#ua! %ows'10000) Index *ond: (#op&" ' 1234)
  12. 12. Inside the Database: Worst Case Speed depends on the number of matched rows and the page fetched. Fetching the last page can take considerably longer than fetching the first page.
  13. 13. Improvement 1: Indexed order by se!e"# * $%om news whe%e #op&" ' 1234 o%de% b( da#e des", &d des" o$$se# 10 !&m&# 10; %&ea"e $ndex on news ("op$%, da"e, $d) A single index to support the whe%e and o%de% b( clauses.
  14. 14. Improvement 1: Indexed order by L&m&# (a%"ua# &ows'10) -> Index S"an Ba")wa%d (a%"ua# &ows'10) Index *ond: (#op&" ' 0)
  15. 15. Improvement 1: Indexed order by L&m&# (a%"ua# &ows'10) -> Index S"an Ba")wa%d (a%"ua# &ows'20) Index *ond: (#op&" ' 0)
  16. 16. Improvement 1: Indexed order by L&m&# (a%"ua# &ows'10) -> Index S"an Ba")wa%d (a%"ua# &ows'30) Index *ond: (#op&" ' 0)
  17. 17. Improvement 1: Indexed order by L&m&# (a%"ua# &ows'10) -> Index S"an Ba")wa%d (a%"ua# &ows'40) Index *ond: (#op&" ' 0)
  18. 18. Improvement 1: Indexed order by L&m&# (a"#ua! %ows'10) -> So%# (a%"ua# &ows'10000) So%# Me#hod: ex"e&na# me&*e D$s): 1200)B -> B&#map Heap S"an (a"#ua! %ows'10000) Re"he") *ond: (#op&" ' 1234) -> B&#map Index S"an (a"#ua! %ows'10000) Index *ond: (#op&" ' 1234)
  19. 19. Improvement 1: Indexed order by Fetching the first page is not affected by the Base-Set size! Fetching the next page is also faster. However, the database might revert to the other execution plan when browsing to the end.
  20. 20. © 2013 by Markus Winand It’s not just about performance
  21. 21. © 2015 by Markus Winand Offsets Yield Unstable Results
  22. 22. © 2015 by Markus Winand Offsets Yield Unstable Results
  23. 23. © 2015 by Markus Winand Offsets Yield Unstable Results
  24. 24. © 2013 by Markus Winand Why don’t we ask for the next rows after...
  25. 25. © 2015 by Markus Winand Asking for “Next After” in SQL
  26. 26. © 2015 by Markus Winand Asking for “Next After” in SQL
  27. 27. © 2015 by Markus Winand Asking for “Next After” in SQL
  28. 28. © 2015 by Markus Winand Asking for “Next After” in SQL
  29. 29. © 2015 by Markus Winand Asking for “Next After” in SQL
  30. 30. © 2015 by Markus Winand Asking for “Next After” in SQL
  31. 31. SQL For “Next After” (Key-Set Pagination) se!e"# * $%om news whe%e #op&" ' 1234 and (da"e, $d) < (?, ?) o%de% b( da#e des", &d des" !&m&# 10 Look Ma, no offset!
  32. 32. Key-Set Pagination: Worst Case
  33. 33. Key-Set Pagination: Worst Case L&m&# (a%"ua# &ows'10) -> So%# (a%"ua# &ows'10) So%# Me#hod: "op-N heapso&" Memo&(: 18)B -> B&#map Heap S"an (&ows'10000) Re"he") *ond: (#op&" ' 1234) -> B&#map Index S"an (&ows'10000) Index *ond: (#op&" ' 1234)
  34. 34. Key-Set Pagination: Worst Case L&m&# (a"#ua! %ows'10) -> So%# (a%"ua# &ows'10) So%# Me#hod: "op-N heapso&" Memo&(: 18)B -> B&#map Heap S"an (a%"ua# &ows'9990) Rows Remo+ed b( F$#"e&: 10 (new &n 9.2) -> B&#map Index S"an (a%"ua# &ows'10000) Index *ond: (#op&" ' 1234)
  35. 35. Key-Set Pagination: Worst Case L&m&# (a"#ua! %ows'10) -> So%# (a%"ua# &ows'10) So%# Me#hod: "op-N heapso&" Memo&(: 18)B -> B&#map Heap S"an (a%"ua# &ows'9980) Rows Remo+ed b( F$#"e&: 20 (new &n 9.2) -> B&#map Index S"an (a%"ua# &ows'10000) Index *ond: (#op&" ' 1234)
  36. 36. Key-Set Pagination: Worst Case L&m&# (a"#ua! %ows'10) -> So%# (a%"ua# &ows'10) So%# Me#hod: "op-N heapso&" Memo&(: 18)B -> B&#map Heap S"an (a%"ua# &ows'9970) Rows Remo+ed b( F$#"e&: 30 (new &n 9.2) -> B&#map Index S"an (a%"ua# &ows'10000) Index *ond: (#op&" ' 1234)
  37. 37. Key-Set Pagination: Worst Case L&m&# (a"#ua! %ows'10) -> So%# (a%"ua# &ows'10) So%# Me#hod: "op-N heapso&" Memo&(: 18)B -> B&#map Heap S"an (a%"ua# &ows'10) Rows Remo+ed b( F$#"e&: 9990 (new &n 9.2) -> B&#map Index S"an (a%"ua# &ows'10000) Index *ond: (#op&" ' 1234)
  38. 38. Key-Set Pagination w/o Index for order by Always needs to retrieve the full base set, but the top-n sort buffer needs to hold only 10 rows. The response time remains the same even when browsing to the last page. And the memory footprint is very low!
  39. 39. Key-Set Pagination: Best Case se!e"# * $%om news whe%e #op&" ' 1234 and (da#e, &d) < (?, ?) o%de% b( da#e des", &d des" !&m&# 10; %&ea"e $ndex on news ("op$%, da"e, $d)
  40. 40. Key-Set Pagination: Best Case L&m&# (a%"ua# &ows'10) -> Index S"an Ba")wa%d (a%"ua# &ows'10) Index *ond: (#op&" ' 1234)
  41. 41. Key-Set Pagination: Best Case L&m&# (a%"ua# &ows'10) -> Index S"an Ba")wa%d (a%"ua# &ows'10) Index *ond: ((#op&" ' 1234) AND (ROW(d#, &d) < ROW(‘...’, 23456)))
  42. 42. Key-Set Pagination: Best Case L&m&# (a%"ua# &ows'10) -> Index S"an Ba")wa%d (a%"ua# &ows'10) Index *ond: ((#op&" ' 1234) AND (ROW(d#, &d) < ROW(‘...’, 34567)))
  43. 43. Key-Set Pagination: Best Case L&m&# (a%"ua# &ows'10) -> Index S"an Ba")wa%d (a%"ua# &ows'10) Index *ond: ((#op&" ' 1234) AND (ROW(d#, &d) < ROW(‘...’, 45678)))
  44. 44. Key-Set Pagination: Best Case L&m&# (a%"ua# &ows'10) -> Index S"an Ba")wa%d (a%"ua# &ows'10) Index *ond: ((#op&" ' 1234) AND (ROW(d#, &d) < ROW(‘...’, 56789)))
  45. 45. Key-Set Pagination: Best Case Successively browsing back doesn’t slow down. Neither the size of the base set(*) nor the fetched page number affects the response time. (*) the index tree depth still affects the response time.
  46. 46. ComparisonOffsetKey-Set Worst Case Best Case
  47. 47. © 2015 by Markus Winand Too good to be true? Key-Set Pagination has serious limitations: ‣You cannot directly navigate to arbitrary pages ‣because you need the values from the previous page ‣Bi-directional navigation is possible but tedious ‣you need to reverse the o%de% b( direction and RV comparison ‣Tooling...???
  48. 48. © 2015 by Markus Winand Required Tooling for Key-Set Pagination
  49. 49. © 2015 by Markus Winand Required Tooling for Key-Set Pagination Proper Row- Values Support. Don’t use OFFSET.NoSQL is also Also for NoSQL
  50. 50. © 2015 by Markus Winand Required Tooling for Key-Set Pagination Proper Row- Values Support. Don’t use OFFSET. Offer Infinite Scrolling. Don’t think in pages. Ask the right question.
  51. 51. OFFSET is EVIL http://use-the-index-luke.com/no-offset
  52. 52. © 2015 by Markus Winand About Markus Winand Tuning developers for high SQL performance Training & co (one-man show): winand.at Geeky blog: use-the-index-luke.com Author of: SQL Performance Explained

×