Зачем знать алгоритмы презентация

Содержание

Who is Mr. Aksenov?

Слайд 1Зачем знать алгоритмы
Андрей Аксенов
Sphinx Technologies Inc.

Highload++2009


Слайд 2Who is Mr. Aksenov?


Слайд 4честно листал все!


Слайд 5не прочитал ни одной :(


Слайд 7делал веб-сайты и веб-движок


Слайд 9делал игры и 3D движок


Слайд 12делаю поисковой движок


Слайд 13free open source search


Слайд 16что могу рассказать?


Слайд 17как устроены всякие движки


Слайд 19на пальцах, не по книжке! (см. “не читатель”)


Слайд 20про движок СУБД (любой)


Слайд 21Система Управления Базой Данных


Слайд 22данные – это таблицы. из строк


Слайд 24строки – нужно где-то хранить


Слайд 27это, кстати, данные – без индексов


Слайд 28добавляем PK, и брюки превращаются…


Слайд 31почему так? разные стратегии хранения строк


Слайд 32MyISAM – в порядке поступления (в конец файла)


Слайд 33InnoDB – хранит постранично, внутри странички – в порядке PK


Слайд 34(InnoDB, после добавления PK)


Слайд 35MyISAM – “обычное” хранение InnoDB – т.н. “кластерное”


Слайд 36умеем хранить – теперь нужно быстро искать!


Слайд 37SELECT * FROM users WHERE id=123


Слайд 38SELECT * FROM users WHERE lastname=‘Pupkin’


Слайд 39SELECT * FROM users WHERE lastname LIKE ‘Pu%’


Слайд 40SELECT * FROM goods WHERE MATCH(‘ipod’) ORDER BY price ASC


Слайд 41SELECT * FROM users WHERE sex=‘F’ AND age>=18 AND age


Слайд 43как выполнять запрос?


Слайд 44полный перебор? мееедленно


Слайд 45нас спасут…


Слайд 47индексы! алгоритмы уже спешат на помощь!


Слайд 48смысл любого вида индекса?


Слайд 49быстрый поиск по ключу(-ам)


Слайд 55видов индексов – тоже много


Слайд 56hash index


Слайд 57R-tree index


Слайд 58full-text index


Слайд 59индекс общего назначения – типично B-tree


Слайд 60поиск – по равенству, диапазону (чисел, строк, и т.п.)


Слайд 61дискует – страничками (хорошо!)


Слайд 62используется – всеми


Слайд 67используется несмотря ни на что!!!


Слайд 68как устроено?


Слайд 69(B-дерево; странички; масштаб 1:72)


Слайд 70два вида страничек


Слайд 71Промежуточные = ключи + указатели на другие странички
{ key1, ptr1, key2,

ptr2, …, keyN }

Слайд 72Листовые = ключи + соотв-е им данные (eg. row_offset)
{ key1, data1,

key2, data2, … }

Слайд 73Промежуточные
Листовые


Слайд 74почему все используют этот ужас?!


Слайд 75во-1х – легко искать по ключу


Слайд 76пример – ищем Зину


Слайд 83ура – Зина нашлась!!!


Слайд 84хорошо – поиск работает…


Слайд 85…но он чё, всегда такой резкий?


Слайд 87– В жизни – под 1000 (а не 3) записей на

страничку – Два уровня страничек – 1000*1000 – миллион – Три уровня – миллиард… – Итого 2-3 странички max – практически всегда

Слайд 88почему все используют этот ужас?!


Слайд 89во-2х – легко обновлять


Слайд 90странички обычно НЕ полны


Слайд 91вставляем…


Слайд 92вставляем…


Слайд 93вставляем… оп-па, некуда!!


Слайд 94создаем новую страничку


Слайд 95создаем новую страничку


Слайд 96…и суем “ее” в родителя


Слайд 97это все – тоже трогаем max 2-3 странички


Слайд 99B-tree Kung Fu!!!


Слайд 100вернемся к запросам?


Слайд 101SELECT * FROM users WHERE id=123
1. “Ищем Зину” (rowoffset по id=123)
2.

seek(rowoffset) в файле строк (.MYD)

3. read(rowdata) из файла

4. и… все – результат готов


Слайд 102усложним – добавим условий


Слайд 103SELECT * FROM users WHERE sex=‘F’ AND age>=18 AND age


Слайд 104индекс “в лоб” по sex?


Слайд 107они ВСЕ подходят по условию ‘F’!


Слайд 109…и нам надо прочитать с диска (!) 5,000,000+ строк…


Слайд 110…и для каждой лично проверить паспорт и age>=18 and age


Слайд 112неселективный индекс – косяк и западло!


Слайд 113sex=‘F’ AND age>=18 AND age


Слайд 114но – вдруг это мужики?!


Слайд 115мужики нам не нужны!!!


Слайд 116либо опять читать ненужные строки (мужиков) – либо…


Слайд 117покрывающий (covering) индекс по обоим полям


Слайд 119список нужных строк – ясен сразу


Слайд 120чтений с диска – минимум скорости – максимум


Слайд 121бонус – сортировка по age


Слайд 122кстати, про сортировку…


Слайд 123SELECT * FROM users WHERE sex=‘F’ AND age>=18 AND age

DESC LIMIT 10

Слайд 124как выполнять? есть варианты


Слайд 126налево – read_index(WHERE) + read_rows + sort_rows(ORDER)


Слайд 127индекс
данные
сортировка
результат


Слайд 128read_index – мало и быстро


Слайд 12910K*( 1+4+8 bytes ) = 130 KB 5-10 ms/seek, 50+ MB/s read


Слайд 130read_random_rows – медленно! 10K*5-10 ms/seek = 50-100 sec…


Слайд 131sort_rows – обычно быстро 10K*0.1-1 KB/row = 1-10 MB (in RAM)


Слайд 132мораль – все зло от random rows!


Слайд 133(еще от sort_rows, если их много)


Слайд 135… sex=‘F’ AND age>=18 AND age


Слайд 136направо – read_fat_index(WHERE) + sort_index(ORDER) + LIMIT + read_less_rows + sort_rows


Слайд 137нужен утолщенный INDEX ( sex, age, hotness )


Слайд 138вместе с поиском по sex, age – сразу узнаем hotness (+40

KB)

Слайд 139sort ( 10K * [ hotness, rowptr ] )


Слайд 140read_rows – почти не нужен (10 строк результата…)


Слайд 141sort_rows – вообще не нужен


Слайд 143не панацея – даже в теории


Слайд 144INDEX ( sex, age, hotness ) WHERE sex=‘F’ ORDER BY hotness LIMIT

10

Слайд 145в теории – обработать 50% индекса затем – прочитать 10 строк (пф!)


Слайд 146INDEX ( sex, age, hotness ) 1M rows, ~20 MB, 50% =

~10 MB

Слайд 147INDEX ( sex, age, hotness ) WHERE sex=‘F’ AND hotness>0 ORDER BY

age LIMIT 10

Слайд 148в теории – читаем индекс линейно – пока не заполним limit


Слайд 149что на практике?


Слайд 150welcome to real world


Слайд 151CREATE 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) )

Слайд 152500,000 записей 56 MB данных (.ibd файл) 32 MB innodb_buffer_pool age \in [18.. 80] hotness

\in [-5.. 5]

Слайд 153mysql> explain select * from usertest where sex='f' and age>=18 and age

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)

Слайд 154filesort – НЕ про временный файл filesort – про “сортировку строк”


Слайд 155Using where – проверка условия НЕ по индексу – ?!!


Слайд 156запрос проще, точно по индексу?


Слайд 157mysql> 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)

Слайд 158проверим экспериментально!!!


Слайд 159mysql> select * from usertest where sex='f' and age>=18 and age

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)

Слайд 160причина?


Слайд 161mysql> explain select * from usertest where sex='f' and age>=18 and age

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)

Слайд 162MySQL не умеет сортировать элементы индекса :(


Слайд 163сортировка “по индексу” – только если индекс гарантирует порядок


Слайд 1641) в куске индекса sex=F, 18


Слайд 1652) optimizer лажанул, 18


Слайд 166(теория говорит – можно лучше!)


Слайд 167проверяем дальше!


Слайд 168mysql> 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)

Слайд 169и последний запрос


Слайд 170mysql> 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)

Слайд 171итого


Слайд 172теория была оптимистична…


Слайд 173…реальность внесла коррективы.


Слайд 174не учли детали реализации


Слайд 1751. нету “досортировки” индекса (MySQL specific)


Слайд 1762. limit обрабатывается… так себе (MySQL specific)


Слайд 1773. optimizer ошибается (везде и у всех)


Слайд 178про ошибки optimizer и спасительный full-scan


Слайд 179mysql> 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)

Слайд 18010,000 x 10 ms = 100 sec 100,000 x 1KB / 50

M/s = 2 sec

Слайд 181мораль: random IO очень плохо (водка яд водка яд водка яд)


Слайд 182про “обработку” limit


Слайд 183теория – приоритетная очередь


Слайд 186технически – heap


Слайд 188или просто double buffer


Слайд 191ключевое свойство – в памяти храним только top-N


Слайд 192LIMIT 10 – надо хранить 10 строк


Слайд 193LIMIT 130,10 – надо 140


Слайд 194практика – MySQL vs. LIMIT


Слайд 195выбрать и отсортировать ВСЕ (*)
* – всегда, когда индекс не гарантирует

точный порядок

Слайд 196выбрать OK – избежать нельзя


Слайд 198сортировать все плохо…


Слайд 200лишний удар по CPU/RAM/IO :(


Слайд 201как убирать mysql сортировку?


Слайд 202строить более другие индексы


Слайд 203ставить более другой софт


Слайд 204умеет и “обычный” поиск!


Слайд 205трюки про WHERE вместо LIMIT (я не пробовал, но говорят, возможно)


Слайд 206…именно в таком порядке.


Слайд 207более практический пример?


Слайд 208импортируем дамп Wikipedia


Слайд 209XML дамп → 2 толстые таблицы хочется – а) одну б) тонкую!


Слайд 210INSERT INTO mycontent 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

Слайд 211mysql> EXPLAIN SELECT t.old_id, ... \G ********************** 1. row **********************

table: page type: ref key: name_title ref: const rows: 4435392 Extra: Using where ********************** 2. row ********************** table: text type: eq_ref key: PRIMARY ref: wiki.p.page_latest rows: 1

Слайд 212что хотим? scan 15 GB text, join 0.5 GB page


Слайд 213почему не выходит? … FROM text t, page p WHERE t.old_id=p.page_latest



Слайд 214решение – index(page_latest)


Слайд 215еще пришлось STRAIGHT_JOIN (optimizer опять лажанул!)


Слайд 216результат – 40 минут, включая CREATE INDEX


Слайд 218так зачем же знать алгоритмы?


Слайд 219“did we learn something today?”


Слайд 221как устроено B-дерево


Слайд 222как работает индекс


Слайд 223как работают выборки


Слайд 224зачем нужны full-scans


Слайд 225как работает сортировка с LIMIT


Слайд 226чего можно добиться в идеале – в теории


Слайд 227…и как оно, бывает, не работает – на практике!


Слайд 228а толку?!


Слайд 229чего ждать от БД


Слайд 230чего не ждать


Слайд 231как и что тестировать


Слайд 232как объяснять потом результаты


Слайд 234в итоге – как заставлять таки работать


Слайд 236…БЫСТРО работать.


Слайд 237“это все” (с) вопросы?!


Обратная связь

Если не удалось найти и скачать презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое ThePresentation.ru?

Это сайт презентаций, докладов, проектов, шаблонов в формате PowerPoint. Мы помогаем школьникам, студентам, учителям, преподавателям хранить и обмениваться учебными материалами с другими пользователями.


Для правообладателей

Яндекс.Метрика