Why02

2,728 views

Published on

Published in: Business, Technology
1 Comment
4 Likes
Statistics
Notes
No Downloads
Views
Total views
2,728
On SlideShare
0
From Embeds
0
Number of Embeds
1,740
Actions
Shares
0
Downloads
78
Comments
1
Likes
4
Embeds 0
No embeds

No notes for slide
  • Объявляю в хате доклад. Меня зовут Андрей Аксенов, и в этом докладе я хочу поделиться своими философскими соображениями на неожиданную тему – зачем вообще разработчику знать алгоритмы.
  • Уверен, что немалой части зала крайне интересно – кто вообще этот человек с микрофоном, и зачем нам его занудная философия ? Вопрос актуальный, нужно пояснить.
  • Why02

    1. 1. Зачем знать алгоритмы Андрей Аксенов Sphinx Technologies Inc. Highload++2009
    2. 2. Who is Mr. Aksenov?
    3. 4. честно листал все !
    4. 5. не прочитал ни одной :(
    5. 7. делал веб-сайты и веб-движок
    6. 9. делал игры и 3D движок
    7. 11. <
    8. 12. делаю поисковой движок
    9. 13. free open source search
    10. 14. << free :(
    11. 16. что могу рассказать?
    12. 17. как устроены всякие движки
    13. 19. на пальцах, не по книжке! (см. “ не читатель ” )
    14. 20. про движок СУБД ( любой )
    15. 21. С истема У правления Б азой Д анных
    16. 22. данные – это таблицы . из строк
    17. 24. строки – нужно где-то хранить
    18. 27. это, кстати, данные – без индексов
    19. 28. добавляем PK, и брюки превращаются…
    20. 31. почему так? разные стратегии хранения строк
    21. 32. MyISAM – в порядке поступления (в конец файла)
    22. 33. InnoDB – хранит постранично, внутри странички – в порядке PK
    23. 34. (InnoDB, после добавления PK)
    24. 35. MyISAM – “ обычное ” хранение InnoDB – т.н. “ кластерное ”
    25. 36. умеем хранить – теперь нужно быстро искать!
    26. 37. SELECT * FROM users WHERE id=123
    27. 38. SELECT * FROM users WHERE lastname=‘Pupkin’
    28. 39. SELECT * FROM users WHERE lastname LIKE ‘Pu%’
    29. 40. SELECT * FROM goods WHERE MATCH(‘ipod’) ORDER BY price ASC
    30. 41. SELECT * FROM users WHERE sex=‘F’ AND age>=18 AND age<=25
    31. 43. как выполнять запрос?
    32. 44. полный перебор ? мееедленно
    33. 45. нас спасут…
    34. 47. индексы! алгоритмы уже спешат на помощь!
    35. 48. смысл любого вида индекса ?
    36. 49. быстрый поиск по ключу(-ам)
    37. 55. видов индексов – тоже много
    38. 56. hash index
    39. 57. R-tree index
    40. 58. full-text index
    41. 59. индекс общего назначения – типично B-tree
    42. 60. поиск – по равенству , диапазону ( чисел, строк, и т.п.)
    43. 61. дискует – страничками (хорошо!)
    44. 62. используется – всеми
    45. 67. используется несмотря ни на что!!!
    46. 68. как устроено?
    47. 69. ( B- дерево ; странички ; масштаб 1: 72) 3 Аня 141 Боря 592 Ваня id key 653 Гоша 589 Дима 793 Ева id key 238 Женя 462 Зина 643 Ира id key 383 Коля 279 Лена 502 Маша id key Аня Гоша Ева Женя Коля Маша Аня Женя Маша
    48. 70. два вида страничек
    49. 71. Промежуточные = ключи + указатели на другие странички { key1, ptr1, key2, ptr2, …, keyN } Аня Женя Маша
    50. 72. Листовые = ключи + соотв-е им данные ( eg. row_offset) { key1, data1, key2, data2, … } Ваня 3 Аня 141 Боря 592 3 Аня 141 Боря 592 Ваня id key
    51. 73. Промежуточные Листовые 3 Аня 141 Боря 592 Ваня id key 653 Гоша 589 Дима 793 Ева id key 238 Женя 462 Зина 643 Ира id key 383 Коля 279 Лена 502 Маша id key Аня Гоша Ева Женя Коля Маша Аня Женя Маша
    52. 74. почему все используют этот ужас?!
    53. 75. во-1х – легко искать по ключу
    54. 76. пример – ищем Зину
    55. 77. 3 Аня 141 Боря 592 Ваня id key 653 Гоша 589 Дима 793 Ева id key 238 Женя 462 Зина 643 Ира id key 383 Коля 279 Лена 502 Маша id key Аня Гоша Ева Женя Коля Маша Аня Женя Маша
    56. 78. 3 Аня 141 Боря 592 Ваня id key 653 Гоша 589 Дима 793 Ева id key 238 Женя 462 Зина 643 Ира id key 383 Коля 279 Лена 502 Маша id key Аня Гоша Ева Женя Коля Маша Аня Женя Маша
    57. 79. 3 Аня 141 Боря 592 Ваня id key 653 Гоша 589 Дима 793 Ева id key 238 Женя 462 Зина 643 Ира id key 383 Коля 279 Лена 502 Маша id key Аня Гоша Ева Женя Коля Маша Аня Женя Маша
    58. 80. 3 Аня 141 Боря 592 Ваня id key 653 Гоша 589 Дима 793 Ева id key 238 Женя 462 Зина 643 Ира id key 383 Коля 279 Лена 502 Маша id key Аня Гоша Ева Женя Коля Маша Аня Женя Маша
    59. 81. 3 Аня 141 Боря 592 Ваня id key 653 Гоша 589 Дима 793 Ева id key 238 Женя 462 Зина 643 Ира id key 383 Коля 279 Лена 502 Маша id key Аня Гоша Ева Женя Коля Маша Аня Женя Маша
    60. 82. 3 Аня 141 Боря 592 Ваня id key 653 Гоша 589 Дима 793 Ева id key 238 Женя 462 Зина 643 Ира id key 383 Коля 279 Лена 502 Маша id key Аня Гоша Ева Женя Коля Маша Аня Женя Маша
    61. 83. ура – Зина нашлась!!!
    62. 84. хорошо – поиск работает…
    63. 85. … но он чё, всегда такой резкий ?
    64. 87. – В жизни – под 1000 (а не 3) записей на страничку – Два уровня страничек – 1000*1000 – миллион – Три уровня – миллиард … – Итого 2-3 странички max – практически всегда 3 Аня 141 Боря 592 Ваня id key 653 Гоша 589 Дима 793 Ева id key 238 Женя 462 Зина 643 Ира id key 383 Коля 279 Лена 502 Маша id key Аня Гоша Ева Женя Коля Маша Аня Женя Маша
    65. 88. почему все используют этот ужас?!
    66. 89. во- 2 х – легко обновлять
    67. 90. странички обычно НЕ полны ? ? 3 Аня ? ? id key
    68. 91. вставляем… ? ? 3 Аня 141 Боря id key
    69. 92. вставляем… 592 Ваня 3 Аня 141 Боря id key
    70. 93. вставляем… оп-па, некуда!! 592 Ваня 653 Гоша 3 Аня 141 Боря id key
    71. 94. создаем новую страничку 592 Ваня 653 Гоша 3 Аня 141 Боря id key ? ? ? ? ? ? ? ? id key
    72. 95. создаем новую страничку ? ? 141 Боря 3 Аня id key ? ? 592 Ваня 653 Гоша id key
    73. 96. … и суем “ ее ” в родителя 141 Боря ? ? 3 Аня id key ? ? 592 Ваня 653 Гоша id key
    74. 97. это все – тоже трогаем max 2-3 странички 141 Боря ? ? 3 Аня id key ? ? 592 Ваня 653 Гоша id key
    75. 99. B-tree Kung Fu!!!
    76. 100. вернемся к запросам?
    77. 101. SELECT * FROM users WHERE id=123 1 . “ Ищем Зину ” (rowoffset по id=123) 2. seek(rowoffset) в файле строк ( .MYD) 3. read(rowdata) из файла 4. и… все – результат готов
    78. 102. усложним – добавим условий
    79. 103. SELECT * FROM users WHERE sex=‘F’ AND age>=18 AND age<=25
    80. 104. индекс “ в лоб ” по sex?
    81. 105. 12352 F 12351 F 12350 F 12349 F 12348 F 12347 F 12346 F 12345 F id key 12360 F 12359 F 12358 F 12357 F 12356 F 12355 F 12354 F 12353 F id key 12368 F 12367 F 12366 F 12365 F 12364 F 12363 F 12362 F 12361 F id key 12376 F 12375 F 12374 F 12373 F 12372 F 12371 F 12370 F 12369 F id key
    82. 106. 12352 F 12351 F 12350 F 12349 F 12348 F 12347 F 12346 F 12345 F id key 12360 F 12359 F 12358 F 12357 F 12356 F 12355 F 12354 F 12353 F id key 12368 F 12367 F 12366 F 12365 F 12364 F 12363 F 12362 F 12361 F id key 12376 F 12375 F 12374 F 12373 F 12372 F 12371 F 12370 F 12369 F id key
    83. 107. они ВСЕ подходят по условию ‘F’!
    84. 109. … и нам надо прочитать с диска (!) 5,000,000+ строк…
    85. 110. … и для каждой лично проверить паспорт и age>=18 and age<=25?!
    86. 111. 12352 F 12351 F 12350 F 12349 F 12348 F 12347 F 12346 F 12345 F id key 12360 F 12359 F 12358 F 12357 F 12356 F 12355 F 12354 F 12353 F id key 12368 F 12367 F 12366 F 12365 F 12364 F 12363 F 12362 F 12361 F id key 12376 F 12375 F 12374 F 12373 F 12372 F 12371 F 12370 F 12369 F id key
    87. 112. неселективный индекс – косяк и западло!
    88. 113. sex=‘F’ AND age>=18 AND age<=25 индекс “ по лбу ” по age?
    89. 114. но – вдруг это мужики?! 12352 16 12351 15 12350 14 12349 14 12348 14 12347 13 12346 13 12345 13 id key 12360 22 12359 21 12358 20 12357 19 12356 18 12355 18 12354 18 12353 17 id key 12368 64 12367 53 12366 42 12365 31 12364 29 12363 27 12362 25 12361 25 id key
    90. 115. мужики нам не нужны!!!
    91. 116. либо опять читать ненужные строки (мужиков) – либо…
    92. 117. покрывающий (covering) индекс по обоим полям
    93. 118. 12352 F, 23 12351 F, 23 12350 F, 22 12349 F, 21 12348 F, 21 12347 F, 19 12346 F, 17 12345 F, 13 id key 12360 M, 17 12359 M, 13 12358 M, 11 12357 F, 42 12356 F, 33 12355 F, 31 12354 F, 27 12353 F, 25 id key 12368 M, 47 12367 M, 43 12366 M, 41 12365 M, 37 12364 M, 31 12363 M, 29 12362 M, 23 12361 M, 19 id key
    94. 119. список нужных строк – ясен сразу
    95. 120. чтений с диска – минимум скорости – максимум
    96. 121. бонус – сортировка по age
    97. 122. кстати, про сортировку …
    98. 123. SELECT * FROM users WHERE sex=‘F’ AND age>=18 AND age<=25 ORDER BY hotness DESC LIMIT 10
    99. 124. как выполнять ? есть варианты
    100. 126. налево – read_index(WHERE) + read_rows + sort_rows(ORDER)
    101. 127. индекс данные сортировка результат 12354 F, 27 12351 F, 23 12350 F, 22 12349 F, 21 12348 F, 21 12347 F, 19 12346 F, 17 12345 F, 13 id key Федор Штын Нина Сидорова Ли Си Цын Маша Петрова Мацал Кошек Шараф Худайбердыев Лена Иванова name Ru Ru Cn Ua Cz Uz Ru Country 12351 80356 … дырка еще на 2000 записей … … дырка на 1000 записей … 24624 12347 10756 24523 12350 id
    102. 128. read_index – мало и быстро
    103. 129. 10 K*( 1+4+8 bytes ) = 130 KB 5-10 ms/seek, 50+ MB/s read
    104. 130. read_ random _rows – медленно ! 10 K *5-10 ms/seek = 50-100 sec…
    105. 131. sort_rows – обычно быстро 10 K*0.1-1 KB/row = 1-10 MB (in RAM)
    106. 132. мораль – все зло от random rows!
    107. 133. (еще от sort_rows , если их много )
    108. 135. … sex=‘F’ AND age>=18 AND age<=25 ORDER BY hotness DESC LIMIT 10
    109. 136. направо – read_ fat _index(WHERE) + sort_index(ORDER) + LIMIT + read_ less _rows + sort_rows
    110. 137. нужен утолщенный INDEX ( sex, age, hotness )
    111. 138. вместе с поиском по sex, age – сразу узнаем hotness (+40 KB)
    112. 139. sort ( 10K * [ hotness, rowptr ] )
    113. 140. read_rows – почти не нужен (10 строк результата…)
    114. 141. sort_rows – вообще не нужен
    115. 142. PROFIT?
    116. 143. не панацея – даже в теории
    117. 144. INDEX ( sex, age, hotness ) WHERE sex=‘F’ ORDER BY hotness LIMIT 10
    118. 145. в теории – обработать 50% индекса затем – прочитать 10 строк (пф!)
    119. 146. INDEX ( sex, age, hotness ) 1M rows, ~20 MB, 50% = ~10 MB
    120. 147. INDEX ( sex, age, hotness ) WHERE sex=‘F’ AND hotness>0 ORDER BY age LIMIT 10
    121. 148. в теории – читаем индекс линейно – пока не заполним limit
    122. 149. что на практике ?
    123. 150. welcome to real world
    124. 151. CREATE TABLE usertest ( id INTEGER PRIMARY KEY NOT NULL, sex ENUM ('m','f'), age INTEGER NOT NULL, hotness INTEGER NOT NULL, name VARCHAR(255) NOT NULL, INDEX (sex,age,hotness) )
    125. 152. 5 00,000 записей 56 MB данных (.ibd файл) 32 MB innodb_buffer_pool age in [ 18 .. 8 0 ] hotness in [-5.. 5 ]
    126. 153. mysql> explain select * from usertest where sex='f' and age>=18 and age<=25 order by hotness desc limit 10 G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: usertest type: ref possible_keys: sex key: sex key_len: 2 ref: const rows: 25119 Extra: Using where; Using filesort 1 row in set (0.00 sec)
    127. 154. filesort – НЕ про временный файл filesort – про “ сортировку строк ”
    128. 155. Using where – проверка условия НЕ по индексу – ?!!
    129. 156. запрос проще , точно по индексу ?
    130. 157. mysql> explain select * from usertest where sex='f' and age=18 order by hotness desc limit 10 G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: usertest type: ref possible_keys: sex key: sex key_len: 6 ref: const,const rows: 10386 Extra: Using where (bug #30733, 30 aug 2007?) 1 row in set (0.00 sec)
    131. 158. проверим экспериментально!!!
    132. 159. mysql> select * from usertest where sex= ' f ' and age>=18 and age<=25 order by hotness desc limit 10; ... 10 rows in set ( 23 .05 sec) mysql> select * from usertest where sex='f' and age=18 order by hotness desc limit 10; ... 10 rows in set (0.05 sec)
    133. 160. причина ?
    134. 161. mysql> explain select * from usertest where sex='f' and age>=18 and age<=25 order by hotness desc limit 10 G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: usertest type: ref possible_keys: sex key: sex key_len: 2  используется только начало, поле “sex”!!! ref: const rows: 25119 Extra: Using where; Using filesort  так и есть :( 1 row in set (0.00 sec)
    135. 162. MySQL не умеет сортировать элементы индекса :(
    136. 163. сортировка “ по индексу ” – только если индекс гарантирует порядок
    137. 164. 1) в куске индекса sex=F, 18<=age<=25 порядок hotness desc НЕ гарантирован
    138. 165. 2) optimizer лажанул, 18<=age<=25 считается НЕ по индексу (а могло бы)
    139. 166. (теория говорит – можно лучше!)
    140. 167. проверяем дальше !
    141. 168. mysql> explain select * from usertest where sex='f' order by hotness desc limit 10 G ... key: sex key_len: 2 ref: const rows: 226072 Extra: Using where; Using filesort mysql> explain select * from usertest where sex='f' order by hotness desc limit 10 G ... 10 rows in set ( 20 . 25 sec)
    142. 169. и последний запрос
    143. 170. mysql> explain select * from usertest where sex='f' and hotness>0 order by age asc limit 10 G ... key: sex key_len: 2 ref: const rows: 226072 Extra: Using where; Using filesort mysql> select * from usertest where sex='f' and hotness>0 order by age asc limit 10; ... 10 rows in set ( 0 . 25 sec)
    144. 171. итого HELL NO 20 . 2 5 Order – Const=F 0. 2 5 0.0 5 23 .05 Time Order Const=18 Range=18..25 Age Cond>0 Order Order Hotness KINDA OK Const=F OK Const=F HELL NO Const=F Optimal Sex
    145. 172. теория была оптимистична…
    146. 173. … реальность внесла коррективы .
    147. 174. не учли детали реализации
    148. 175. 1. нету “ досортировки ” индекса (MySQL specific)
    149. 176. 2. limit обрабатывается … так себе (MySQL specific)
    150. 177. 3 . optimizer ошибается (везде и у всех)
    151. 178. про ошибки optimizer и спасительный full-scan
    152. 179. mysql> select * from usertest where sex='f' order by hotness desc limit 10; ... 10 rows in set (20.25 sec) mysql> select * from usertest ignore index(sex) where sex='f' order by hotness desc limit 10; ... 10 rows in set (0.55 sec)
    153. 180. 10,000 x 10 ms = 100 sec 100,000 x 1KB / 50 M/s = 2 sec
    154. 181. мораль : random IO очень плохо (водка яд водка яд водка яд)
    155. 182. про “ обработку ” limit
    156. 183. теория – приоритетная очередь
    157. 185. приоритетная !!
    158. 186. технически – heap
    159. 188. или просто double buffer
    160. 191. ключевое свойство – в памяти храним только top-N
    161. 192. LIMIT 10 – надо хранить 10 строк
    162. 193. LIMIT 1 3 0,10 – надо 1 4 0
    163. 194. практика – MySQL vs. LIMIT
    164. 195. выбрать и отсортировать ВСЕ (*) * – всегда, когда индекс не гарантирует точный порядок
    165. 196. выбрать OK – избежать нельзя
    166. 198. сортировать все плохо …
    167. 200. лишний удар по CPU/RAM/IO :(
    168. 201. как убирать mysql сортировку ?
    169. 202. строить более другие индексы
    170. 203. ставить более другой софт
    171. 204. умеет и “ обычный ” поиск !
    172. 205. трюки про WHERE вместо LIMIT ( я не пробовал, но говорят, возможно)
    173. 206. … именно в таком порядке.
    174. 207. более практический пример ?
    175. 208. импортируем дамп Wikipedia
    176. 209. XML дамп -> 2 толстые таблицы хочется – а) одну б) тонкую !
    177. 210. INSERT INTO my content SELECT t.old_id, p.page_id, UNIX_TIMESTAMP(p.page_touched), p.page_len, p.page_title, COMPRESS(t.old_text) FROM text t, page p WHERE t.old_id=p.page_latest AND page_namespace=0 AND page_is_redirect=0; 15 GB text, 0.5 GB page, ~4.5M rows tps=~200, bi/bo=~1 MB/sec ~200 MB .MYD in ~20 mins, ETA 10+ hrs
    178. 211. mysql> EXPLAIN SELECT t.old_id, ... G ********************** 1. row ********************** table: p age type: ref key: name_title ref: const rows: 4435392 Extra: Using where ********************** 2. row ********************** table: t ext type: eq_ref key: PRIMARY ref: wiki.p.page_latest rows: 1
    179. 212. что хотим? scan 15 GB text, join 0.5 GB page
    180. 213. почему не выходит ? … FROM text t, page p WHERE t.old_id= p.page_latest
    181. 214. решение – index(page_latest)
    182. 215. еще пришлось STRAIGHT_JOIN (optimizer опять лажанул!)
    183. 216. результат – 40 минут , включая CREATE INDEX
    184. 218. так зачем же знать алгоритмы?
    185. 219. “ did we learn something today?”
    186. 221. как устроено B- дерево
    187. 222. как работает индекс
    188. 223. как работают выборки
    189. 224. зачем нужны full-scans
    190. 225. как работает сортировка с LIMIT
    191. 226. чего можно добиться в идеале – в теории
    192. 227. … и как оно, бывает, не работает – на практике !
    193. 228. а толку?!
    194. 229. чего ждать от БД
    195. 230. чего не ждать
    196. 231. как и что тестировать
    197. 232. как объяснять потом результаты
    198. 234. в итоге – как заставлять таки работать
    199. 236. … БЫСТРО работать.
    200. 237. “ это все ” (с) вопросы ?!

    ×