{"id":33793,"date":"2019-10-31T21:54:42","date_gmt":"2019-10-31T18:54:42","guid":{"rendered":"https:\/\/prohoster.info\/blog\/bitmap-indeksy-v-go-poisk-na-dikoj-skorosti\/"},"modified":"2019-10-31T21:54:42","modified_gmt":"2019-10-31T18:54:42","slug":"bitmap-indeksy-v-go-poisk-na-dikoj-skorosti","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/bitmap-indeksy-v-go-poisk-na-dikoj-skorosti","title":{"rendered":"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/86ef928e6741022b2c0e5885a031408a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Einleitende Worte<\/h2>\n<p>\nIch habe diesen Vortrag auf Englisch auf der GopherCon Russland 2019 in Moskau gehalten und auf Russisch beim Meetup in Nischni Nowgorod. Es geht um Bitmap-Indizes \u2013 weniger verbreitet als B-B\u00e4ume, aber nicht weniger interessant. Ich teile <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/WvlUH6MjUuI?list=PL3xVZC4USRNSO_kb2lh_J_no6C-KJ7Phg\">die Aufzeichnung<\/a><\/noindex> meiner Pr\u00e4sentation auf der Konferenz in Englisch und die schriftliche Transkription auf Russisch.<\/p>\n<p>Wir werden betrachten, wie ein Bitmap-Index aufgebaut ist, wann er besser ist als andere Indizes und wann er deutlich schneller ist; wir sehen uns an, in welchen beliebten DBMS es bereits Bitmap-Indizes gibt; und versuchen, unseren eigenen in Go zu schreiben. Als \u201aDessert\u2018 nutzen wir vorhandene Bibliotheken, um unsere superschnelle spezialisierte Datenbank zu erstellen.<\/p>\n<p>Ich hoffe sehr, dass meine Arbeit f\u00fcr Sie n\u00fctzlich und interessant ist. Lassen Sie uns beginnen!<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Einf\u00fchrung<\/h2>\n<p>\n<center><div class=\"youtube-placeholder\" data-id=\"WvlUH6MjUuI\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/WvlUH6MjUuI\/hqdefault.jpg\" alt=\"Video abspielen\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\n<noindex><a rel=\"nofollow\" href=\"http:\/\/bit.ly\/bitmapindexes\">http:\/\/bit.ly\/bitmapindexes<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/mkevac\/gopherconrussia2019\">https:\/\/github.com\/mkevac\/gopherconrussia2019<\/a><\/noindex><\/p>\n<p>Hallo zusammen! Es ist jetzt sechs Uhr abends, und wir sind alle super m\u00fcde. Eine wunderbare Zeit, um \u00fcber die langweilige Theorie von Datenbankindizes zu sprechen, oder? Keine Sorge, ich werde hier und da ein paar Codezeilen haben. \ud83d\ude42<\/p>\n<p>Im Ernst, der Vortrag ist voller Informationen, und wir haben nicht viel Zeit. Lassen Sie uns also anfangen.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/e778e13727700f0335a4b5558a0d8db3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nHeute werde ich \u00fcber Folgendes sprechen:<\/p>\n<ul>\n<li>Was sind Indizes?\n<\/li>\n<li>Was ist ein Bitmap-Index?\n<\/li>\n<li>Wo wird er eingesetzt und wo nicht, und warum?\n<\/li>\n<li>Einfache Implementierung in Go und ein wenig K\u00e4mpfen mit dem Compiler.\n<\/li>\n<li>Etwas weniger einfach, aber deutlich leistungsf\u00e4higere Implementierung in Go-Assembler.\n<\/li>\n<li>Die \"Probleme\" von Bitmap-Indizes.\n<\/li>\n<li>Bestehende Implementierungen.\n<\/li>\n<\/ul>\n<h2>Also, was sind Indizes?<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/b80e5b990c44814afe9150a9a82351fd.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEin Index ist eine separate Datenstruktur, die wir zus\u00e4tzlich zu den Hauptdaten halten und aktualisieren. Sie wird verwendet, um die Suche zu beschleunigen. Ohne Indizes w\u00fcrde die Suche einen vollst\u00e4ndigen Durchgang durch die Daten erfordern (ein Prozess, der als Full Scan bezeichnet wird), und dieser Prozess hat eine lineare algorithmische Komplexit\u00e4t. Aber Datenbanken enthalten normalerweise eine riesige Menge an Daten, und lineare Komplexit\u00e4t ist zu langsam. Idealerweise h\u00e4tten wir logarithmische oder konstante Komplexit\u00e4t.<\/p>\n<p>Das ist ein riesiges, komplexes Thema, das voller Feinheiten und Kompromisse ist, aber nachdem ich jahrzehntelange Entwicklungen und Forschungen zu verschiedenen Datenbanken betrachtet habe, bin ich bereit zu behaupten, dass es nur wenige weit verbreitete Ans\u00e4tze zur Erstellung von Datenbankindizes gibt.<\/p>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/08a74dbb365035cd99bc94d72644a1b7.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDer erste Ansatz besteht darin, den Suchbereich hierarchisch zu verkleinern, indem man ihn in kleinere Teile aufteilt.<\/p>\n<p>In der Regel tun wir dies, indem wir verschiedene Arten von B\u00e4umen verwenden. Ein Beispiel daf\u00fcr k\u00f6nnte eine gro\u00dfe Kiste mit Materialien in Ihrem Schrank sein, in der sich kleinere Kisten mit Materialien zu verschiedenen Themen befinden. Wenn Sie Materialien ben\u00f6tigen, suchen Sie sicherlich in der Kiste mit der Beschriftung \"Materialien\" und nicht in der, auf der \"Kekse\" steht, oder?<\/p>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/423fac47c748980b18af434644af4dae.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDer zweite Ansatz besteht darin, sofort das gesuchte Element oder eine Gruppe von Elementen zu identifizieren. Dies geschieht in Hash-Maps oder in umgekehrten Indizes. Die Nutzung von Hash-Maps \u00e4hnelt dem vorherigen Beispiel, nur dass Sie anstelle einer Kiste mit Kisten eine Vielzahl von kleinen Boxen mit endg\u00fcltigen Objekten in Ihrem Schrank haben.<\/p>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/088fed0a2a0feea4a23edbf0ca654805.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDer dritte Ansatz ist, die Notwendigkeit einer Suche zu eliminieren. Dies erreichen wir mit Bloom-Filtern oder Cuckoo-Filtern. Erstere liefern die Antwort sofort und befreien Sie von der Notwendigkeit zu suchen.<\/p>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/493bc4f20baacc0a5dc0faf15cc46285.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDer letzte Ansatz besteht darin, alle M\u00f6glichkeiten, die moderne Hardware bietet, vollst\u00e4ndig zu nutzen. Genau das tun wir bei Bitmap-Indizes. Ja, manchmal m\u00fcssen wir den gesamten Index durchlaufen, aber wir machen dies super effizient.<\/p>\n<p>Wie ich bereits erw\u00e4hnt habe, ist das Thema Datenbankindizes umfangreich und voller Kompromisse. Das bedeutet, dass wir manchmal mehrere Ans\u00e4tze gleichzeitig nutzen k\u00f6nnen: wenn wir die Suche noch weiter beschleunigen m\u00fcssen oder wenn es erforderlich ist, alle m\u00f6glichen Suchtypen abzudecken.<\/p>\n<p>Heute werde ich \u00fcber die am wenigsten bekannte Methode sprechen \u2014 die Bitmap-Indizes.<\/p>\n<h2>Wer bin ich, um \u00fcber dieses Thema zu sprechen?<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/42a9d17a507c392bc202254a92dfaf41.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIch arbeite als Teamleiter bei Badoo (vielleicht kennen Sie unser anderes Produkt besser \u2014 Bumble). Wir haben \u00fcber 400 Millionen Nutzer weltweit und viele Funktionen, die darauf abzielen, das beste Matching zu finden. Dabei nutzen wir ma\u00dfgeschneiderte Services, die unter anderem auch Bitmap-Indizes einsetzen.<\/p>\n<h2>Was ist also ein Bitmap-Index?<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/14f20f3697a20c02f6b3510dc7f0ae4d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nBitmap-Indizes verwenden, wie der Name schon sagt, Bitmaps oder Bitsets, um einen Suchindex zu implementieren. Aus der Vogelperspektive besteht dieser Index aus einem oder mehreren dieser Bitmaps, die bestimmte Entit\u00e4ten (wie Personen) und deren Eigenschaften oder Parameter (Alter, Augenfarbe usw.) repr\u00e4sentieren, sowie aus einem Algorithmus, der bitweise Operationen (UND, ODER, NICHT) nutzt, um Suchanfragen zu beantworten.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/f815720330a51b1f0798e45d23160d3b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEs wird gesagt, dass Bitmap-Indizes am besten geeignet und sehr leistungsf\u00e4hig sind f\u00fcr F\u00e4lle, in denen Suchanfragen mehrere Spalten mit geringer Kardinalit\u00e4t kombinieren (denken Sie an 'Augenfarbe' oder 'Familienstand' im Gegensatz zu etwas wie 'Entfernung zum Stadtzentrum'). Aber sp\u00e4ter werde ich zeigen, dass sie auch bei Spalten mit hoher Kardinalit\u00e4t hervorragend funktionieren.<\/p>\n<p>Lassen Sie uns ein einfaches Beispiel f\u00fcr einen Bitmap-Index betrachten.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/33fe23476e0931c10345d7175b83d68b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nStellen Sie sich vor, dass wir eine Liste von Restaurants in Moskau mit bin\u00e4ren Eigenschaften wie diesen haben:<\/p>\n<ul>\n<li>in der N\u00e4he der U-Bahn (near metro);\n<\/li>\n<li>mit privatem Parkplatz (has private parking);\n<\/li>\n<li>mit Terrasse (has terrace);\n<\/li>\n<li>mit Tischreservierungen (accepts reservations);\n<\/li>\n<li>veganfreundlich (vegan friendly);\n<\/li>\n<li>teuer (expensive).\n<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/fcbad539ea12f79a9d06966ce308637e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nLassen Sie uns jedem Restaurant eine fortlaufende Nummer ab 0 geben und Speicher f\u00fcr 6 Bitmaps reservieren (je eines f\u00fcr jedes Merkmal). Dann f\u00fcllen wir diese Bitmaps abh\u00e4ngig davon aus, ob das Restaurant das jeweilige Merkmal besitzt oder nicht. Hat Restaurant 4 eine Terrasse, wird das Bit Nr. 4 im Bitmap \"hat Terrasse\" auf 1 gesetzt (wenn keine Terrasse vorhanden ist, auf 0).<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/3709c426617d4364f392ee6b68f92b00.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nJetzt haben wir den einfachsten Bitmap-Index, den es gibt, und wir k\u00f6nnen ihn verwenden, um auf Anfragen zu antworten wie:<\/p>\n<ul>\n<li>\"Zeig mir Restaurants, die f\u00fcr Vegetarier geeignet sind\";\n<\/li>\n<li>\"Zeig mir preiswerte Restaurants mit Terrasse, in denen man einen Tisch reservieren kann.\"\n<\/li>\n<\/ul>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/90acb0f890686bd52c3db1fc667f0b0b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/0fd0b7fe9f7b7039022ad5c79fe873bc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWie? Schauen wir uns das an. Die erste Anfrage ist sehr einfach. Alles, was wir tun m\u00fcssen, ist, das Bitmap \"geeignet f\u00fcr Vegetarier\" zu nehmen und es in eine Liste von Restaurants umzuwandeln, deren Bits gesetzt sind.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/ef4a5cfd658ff4ef8bc0c638c4522d11.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/9cc175bae55c16018fdf5ff95517a61a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDie zweite Anfrage ist etwas komplexer. Wir m\u00fcssen die BIT-NOT-Operation auf der Bitmap \"teuer\" verwenden, um eine Liste von g\u00fcnstigen Restaurants zu erhalten. Dann verkn\u00fcpfen wir sie mit der Bitmap \"Reservierung m\u00f6glich\" und kombinieren das Ergebnis mit der Bitmap \"hat eine Terrasse\". Die resultierende Bitmap wird eine Liste von Einrichtungen enthalten, die all unseren Kriterien entsprechen. In diesem Beispiel ist das nur das Restaurant \"Junge Jahre\".<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/f1cdda0cbf7f15278553899cf876c17e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/126b50e0f622b6e36c461cd74e708c38.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nHier gibt es viel Theorie, aber keine Sorge, wir werden bald den Code sehen.<\/p>\n<h2>Wo werden Bitmap-Indizes verwendet?<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/406132236c71a4f66ae79957b6e633b3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWenn Sie \"Bitmap-Indizes googeln\", werden 90 % der Antworten irgendwie mit Oracle DB verbunden sein. Aber auch andere DBMS unterst\u00fctzen diese coole Funktion, oder? Nicht ganz. <\/p>\n<p>Lassen Sie uns die Liste der Hauptverd\u00e4chtigen durchgehen.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/d18d66451a8a26b0ddf121f8ec0204cd.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nMySQL unterst\u00fctzt Bitmap-Indizes noch nicht, aber es gibt einen Vorschlag, diese Option hinzuzuf\u00fcgen (<noindex><a rel=\"nofollow\" href=\"https:\/\/dev.mysql.com\/worklog\/task\/?id=1524\">https:\/\/dev.mysql.com\/worklog\/task\/?id=1524<\/a><\/noindex>).<\/p>\n<p>PostgreSQL unterst\u00fctzt keine Bitmap-Indizes, verwendet jedoch einfache Bitmaps und Bitoperationen zur Kombination von Suchergebnissen \u00fcber mehrere andere Indizes.<\/p>\n<p>Tarantool hat Bitset-Indizes, es unterst\u00fctzt einfache Suchen darauf.<\/p>\n<p>Redis hat einfache Bitfelder<noindex><a rel=\"nofollow\" href=\"https:\/\/redis.io\/commands\/bitfield\"> (https:\/\/redis.io\/commands\/bitfield<\/a><\/noindex>) ohne die M\u00f6glichkeit, danach zu suchen.<\/p>\n<p>MongoDB unterst\u00fctzt noch keine Bitmap-Indizes, es gibt jedoch einen Vorschlag zur Hinzunahme dieser Option. <noindex><a rel=\"nofollow\" href=\"https:\/\/jira.mongodb.org\/browse\/SERVER-1723\">https:\/\/jira.mongodb.org\/browse\/SERVER-1723<\/a><\/noindex><\/p>\n<p>Elasticsearch verwendet Bitmaps intern.<noindex><a rel=\"nofollow\" href=\"https:\/\/www.elastic.co\/blog\/frame-of-reference-and-roaring-bitmaps\"> (https:\/\/www.elastic.co\/blog\/frame-of-reference-and-roaring-bitmaps<\/a><\/noindex>).<\/p>\n<p>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/232d335963603d6e6dec98839fc9f486.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<ul>\n<li>Aber in unserem Haus hat ein neuer Nachbar Einzug gehalten: Pilosa. Dies ist eine neue nicht-relationale Datenbank, die in Go geschrieben wurde. Sie enth\u00e4lt ausschlie\u00dflich Bitmap-Indizes und basiert komplett auf ihnen. Dar\u00fcber werden wir sp\u00e4ter sprechen.\n<\/li>\n<\/ul>\n<h2>Implementierung in Go<\/h2>\n<p>\nWarum werden Bitmap-Indizes jedoch so selten verwendet? Bevor ich diese Frage beantworte, m\u00f6chte ich Ihnen eine sehr einfache Implementierung eines Bitmap-Index in Go demonstrieren.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/ae7f4c1a4a740fe709b05dfaee27ac9b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nBitmaps sind im Wesentlichen einfach Datenst\u00fccke. In Go verwenden wir daf\u00fcr Byte-Slices.<\/p>\n<p>Wir haben einen Bitmap f\u00fcr ein Restaurantmerkmal, und jedes Bit im Bitmap zeigt an, ob ein bestimmtes Restaurant dieses Merkmal hat oder nicht.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/1ab628ee15887d6b3c6c99855aa610c8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWir ben\u00f6tigen zwei Hilfsfunktionen. Eine wird verwendet, um unsere Bitmaps mit zuf\u00e4lligen Daten zu f\u00fcllen. Zuf\u00e4llig, aber mit einer bestimmten Wahrscheinlichkeit, dass ein Restaurant bestimmte Eigenschaften aufweist. Zum Beispiel denke ich, dass es in Moskau sehr wenige Restaurants gibt, in denen man keinen Tisch reservieren kann, und ich sch\u00e4tze, dass etwa 20 % der Lokale f\u00fcr Vegetarier geeignet sind.<\/p>\n<p>Die zweite Funktion wird das Bitmap in eine Liste von Restaurants umwandeln.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/ab9c87a0ba63750116e2e7968f842a9a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/498cf7a33611d99b90197d4ee82e2834.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nUm die Anfrage \u201eZeig mir preiswerte Restaurants mit einer Terrasse, in denen man einen Tisch reservieren kann\u201c zu beantworten, ben\u00f6tigen wir zwei bitweise Operationen: NOT und AND.<\/p>\n<p>Wir k\u00f6nnen unseren Code etwas vereinfachen, indem wir eine komplexere Operation AND NOT verwenden.<\/p>\n<p>Wir haben Funktionen f\u00fcr jede dieser Operationen. Beide durchlaufen die Slices, nehmen die entsprechenden Elemente aus jedem, f\u00fchren die bitweise Operation durch und speichern das Ergebnis in dem Ergebnis-Slice.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/ec5652a34f0370dfb03df199f341f153.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nUnd jetzt k\u00f6nnen wir unsere Bitmaps und Funktionen nutzen, um die Suchanfrage zu beantworten.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/cf9500ccfe75995a6008191c16729689.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDie Leistung ist nicht so hoch, obwohl die Funktionen sehr einfach sind und wir betr\u00e4chtliche Einsparungen erzielt haben, da wir bei jedem Funktionsaufruf nicht einen neuen Resultats-Slice zur\u00fcckgegeben haben.<\/p>\n<p>Nach ein wenig Profilerstellung mit pprof bemerkte ich, dass der Go-Compiler eine sehr einfache, aber \u00e4u\u00dferst wichtige Optimierung ausgelassen hat: das Inlining von Funktionen.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/9092f5ba3940d0a4f3fbfa90b364d716.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDas Problem ist, dass der Go-Compiler gro\u00dfe Angst vor Schleifen hat, die \u00fcber Slices gehen, und kategorisch ablehnt, Funktionen zu inlinen, die solche Schleifen enthalten.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/d1bddd62b61b367dd1f680f223fa0ce7.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAber ich habe keine Angst und kann den Compiler t\u00e4uschen, indem ich anstelle einer Schleife goto verwende, wie in alten Zeiten.<\/p>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/5b1c3cb26b923972686047910ecd1c31.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/1ca31d12dc90931b674c6a86a4ea23bd.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUnd wie Sie sehen, inline der Compiler jetzt gerne unsere Funktion! Letztendlich gelingt es uns, etwa 2 Mikrosekunden zu sparen. Gar nicht schlecht!<\/p>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/bdd6735d16082573e600bffe2cdd5662.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDas zweite Engpass ist leicht zu erkennen, wenn man den Assembler-Ausgabe aufmerksam betrachtet. Der Compiler hat eine \u00dcberpr\u00fcfung der Slice-Grenzen direkt in unseren hei\u00dfesten Schleifen eingef\u00fcgt. Das Problem ist, dass Go eine sichere Sprache ist und der Compiler bef\u00fcrchtet, dass meine drei Argumente (drei Slices) unterschiedliche Gr\u00f6\u00dfen haben. Dadurch k\u00f6nnte theoretisch ein so genanntes Buffer Overflow entstehen.<\/p>\n<p>Lassen Sie uns den Compiler beruhigen, indem wir ihm zeigen, dass alle Slices die gleiche Gr\u00f6\u00dfe haben. Das k\u00f6nnen wir erreichen, indem wir zu Beginn unserer Funktion eine einfache \u00dcberpr\u00fcfung hinzuf\u00fcgen.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/59b4ce687a11dd653e9f12fc3130d89a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWenn der Compiler das sieht, l\u00e4sst er die \u00dcberpr\u00fcfung gerne aus, und wir sparen am Ende weitere 500 Nanosekunden.<\/p>\n<h2>Gro\u00dfe Batches<\/h2>\n<p>\nOkay, wir haben eine gewisse Leistung aus unserer einfachen Implementierung herausgeholt, aber dieses Ergebnis ist tats\u00e4chlich viel schlechter, als es mit der aktuellen Hardware m\u00f6glich w\u00e4re.<\/p>\n<p>Alles, was wir tun, sind grundlegende bitweise Operationen, und unsere Prozessoren f\u00fchren diese sehr effizient aus. Leider \"f\u00fcttern\" wir unseren Prozessor jedoch mit sehr kleinen Arbeitsst\u00fccken. Unsere Funktionen f\u00fchren Operationen byteweise aus. Es ist ganz einfach, unseren Code so zu optimieren, dass er mit 8-Byte-St\u00fccken arbeitet, indem wir UInt64-Slices verwenden.<\/p>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/8d1b60ba4b7046c836601631cadd0b6a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWie Sie sehen k\u00f6nnen, hat diese kleine \u00c4nderung unser Programm um das Achtfache beschleunigt, indem die Batch-Gr\u00f6\u00dfe um das Achtfache erh\u00f6ht wurde. Der Gewinn ist sozusagen linear.<\/p>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/0fc663412d04dd38b927de5c8776f69d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h2>Implementierung in Assembler<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/b3ef133167b89da983356b1c7389aecd.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAber das ist noch nicht das Ende. Unsere Prozessoren k\u00f6nnen mit St\u00fccken von 16, 32 und sogar 64 Byte arbeiten. Solche \"breiten\" Operationen werden als Single Instruction Multiple Data (SIMD; eine Anweisung, viele Daten) bezeichnet, und der Prozess, der den Code so umgestaltet, dass er solche Operationen nutzt, wird als Vektorisierung bezeichnet.<\/p>\n<p>Leider ist der Go-Compiler nicht gerade ein Meister in der Vektorisierung. Derzeit gibt es keinen anderen Weg, um Go-Code zu vektorisieren, als die Datenoperationen manuell mithilfe von Go-Assembler zu organisieren.<\/p>\n<p><img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/91278be45df67e1f9572d68fab7ebad1.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nGo-Assembler ist ein interessantes Ph\u00e4nomen. Sie wissen wahrscheinlich, dass ein Assembler stark an die Architektur des Computers gebunden ist, f\u00fcr den Sie schreiben, aber im Fall von Go ist das nicht so. Go-Assembler \u00e4hnelt mehr einer IRL (Intermediate Representation Language) oder einer Zwischenrepr\u00e4sentation: Er ist nahezu plattformunabh\u00e4ngig. Rob Pike hat vor einigen Jahren auf der GopherCon in Denver einen hervorragenden Vortrag zu diesem Thema gehalten. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=KINIAgRpkDA\">\u00fcber<\/a><\/noindex> Zus\u00e4tzlich dazu verwendet Go ein ungew\u00f6hnliches Format von Plan 9, das sich von den allgemein anerkannten Formaten AT&amp;T und Intel unterscheidet.<\/p>\n<p>Es l\u00e4sst sich mit Sicherheit sagen, dass das manuelle Schreiben von Go-Assembler nicht die unterhaltsamste Aufgabe ist.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/526f75eb18edfc2f851f2725e9d6f69e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAber gl\u00fccklicherweise gibt es bereits zwei hochentwickelte Tools, die uns beim Schreiben von Go-Assembler helfen: PeachPy und avo. Beide Werkzeuge generieren Go-Assembler aus h\u00f6herstufigem Code, der entweder in Python oder Go geschrieben ist.<\/p>\n<p>Diese Tools erleichtern Aufgaben wie die Zuweisung von Registern, das Schreiben von Schleifen und vereinfachen insgesamt den Einstieg in die Welt der Assembler-Programmierung in Go.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/b8a7aa2c585b805e9b1f2ada186b84e8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWir werden avo verwenden, sodass unsere Programme nahezu normale Go-Programme sein werden.<\/p>\n<p>Wir werden avo verwenden, sodass unsere Programme fast wie ganz normale Go-Programme sind.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/128e4adef14e5f2cf00fb5b6302ef58e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSo sieht das einfachste Beispiel eines Avo-Programms aus. Wir haben eine Funktion main(), die innerhalb ihr eine Funktion Add() definiert, deren Aufgabe es ist, zwei Zahlen zu addieren. Hier sind Hilfsfunktionen vorhanden, um Parameter nach Namen zu erhalten und einen der verf\u00fcgbaren geeigneten Prozessorregister abzurufen. Jede Prozessoroperation hat die entsprechende Funktion in Avo, wie bei ADDQ zu sehen ist. Und schlie\u00dflich sehen wir eine Hilfsfunktion zum Speichern des Ergebniswerts.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/01ccaa6aa6d394ef598ea2dbc9257d87.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWenn wir go generate aufrufen, f\u00fchren wir das Programm in Avo aus, und am Ende werden zwei Dateien generiert:<\/p>\n<ul>\n<li>add.s mit dem resultierenden Code in Go-Assembler;\n<\/li>\n<li>stub.go mit Funktionskopfzeilen zur Verbindung der beiden Welten: Go und Assembler.\n<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/72a9443776ecf45eef6fb97a4e08acba.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nNun, da wir gesehen haben, was Avo tut und wie es funktioniert, schauen wir uns unsere Funktionen an. Ich habe sowohl die Skalare als auch die Vektorversionen (SIMD) der Funktionen implementiert.<\/p>\n<p>Zuerst werfen wir einen Blick auf die skalaren Versionen.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/ec31dbb8b97b9d7c1012a120fa18cdaf.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWie im vorherigen Beispiel bitten wir darum, uns ein freies und geeignetes allgemeines Register bereitzustellen; wir m\u00fcssen keine Offsets und Gr\u00f6\u00dfen f\u00fcr die Argumente berechnen. All das erledigt Avo f\u00fcr uns.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/88085e927dd943ea0f808a28fb3ccf9b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nFr\u00fcher haben wir Labels und Goto (oder Spr\u00fcnge) verwendet, um die Leistung zu steigern und den Go-Compiler auszutricksen, aber jetzt machen wir das von Grund auf neu. Das Problem ist, dass Schleifen ein h\u00f6heres Konzept sind. Im Assembler haben wir nur Labels und Spr\u00fcnge.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/9a4181248eb279d89c1445a820b06649.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDer verbleibende Code sollte Ihnen bereits vertraut und verst\u00e4ndlich sein. Wir emulieren eine Schleife mit Labels und Spr\u00fcngen, nehmen einen kleinen Teil der Daten aus unseren beiden Slices, kombinieren sie mit einer Bitoperation (in diesem Fall AND NOT) und legen das Ergebnis dann in den Ergebnis-Slice. Das war's.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/19275ead27f63092fc6596bed38a8d03.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSo sieht der endg\u00fcltige Code in Assembler aus. Wir mussten keine Offsets und Gr\u00f6\u00dfen berechnen (gr\u00fcn hervorgehoben) oder die verwendeten Register \u00fcberwachen (rot hervorgehoben).<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/ed68528a6f852634a5b536670c6315f0.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWenn wir die Leistung der Implementierung in Assembler mit der Leistung der besten Implementierung in Go vergleichen, werden wir feststellen, dass sie gleich ist. Und das ist zu erwarten. Schlie\u00dflich haben wir nichts Besonderes getan \u2013 wir haben nur reproduziert, was der Go-Compiler tun w\u00fcrde.<\/p>\n<p>Leider kann der Compiler unsere in Assembler geschriebenen Funktionen nicht inline einf\u00fcgen. Der Go-Compiler bietet diese M\u00f6glichkeit derzeit nicht, obwohl die Bitte, dies hinzuzuf\u00fcgen, schon seit geraumer Zeit besteht.<\/p>\n<p>Genau deshalb ist es nicht m\u00f6glich, irgendwelche Vorteile aus kleineren Assembler-Funktionen zu ziehen. Wir m\u00fcssen gro\u00dfe Funktionen schreiben, ein neues Paket math\/bits verwenden oder Assembler ganz umgehen.<\/p>\n<p>Lassen Sie uns nun die vektorisierten Versionen unserer Funktionen betrachten.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/7f67c3cc855908fb47c7900d6e5d7f54.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nF\u00fcr dieses Beispiel habe ich beschlossen, AVX2 anzuwenden, daher verwenden wir Operationen, die mit 32-Byte-St\u00fcckchen arbeiten. Die Struktur des Codes ist sehr \u00e4hnlich der skalaren Version: Parameter laden, um einen freien allgemeinen Register zu bitten usw.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/021e0424a0d733ec7db9edeb98ce1f65.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEine der Neuerungen besteht darin, dass breitere Vektoroperationen spezielle breite Register verwenden. Im Fall von 32-Byte-St\u00fccken sind dies die Register mit dem Pr\u00e4fix Y. Deshalb sehen Sie die Funktion YMM() im Code. Wenn ich AVX-512 mit 64-Bit-St\u00fccken verwenden w\u00fcrde, w\u00e4re das Pr\u00e4fix Z.<\/p>\n<p>Die zweite Neuerung besteht darin, dass ich eine Optimierung eingef\u00fchrt habe, die als Loop Unrolling bekannt ist. Das bedeutet, dass ich acht Schleifenoperationen manuell durchgef\u00fchrt habe, bevor ich zum Anfang der Schleife zur\u00fccksprung. Diese Optimierung verringert die Anzahl der Verzweigungen im Code und ist durch die Anzahl der verf\u00fcgbaren Register begrenzt.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/f54631d9e8c69f6f70ecace3133ae1e8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWie sieht es mit der Leistung aus? Sie ist hervorragend! Wir haben eine Beschleunigung von etwa sieben Mal im Vergleich zur besten L\u00f6sung in Go erreicht. Beeindruckend, oder?<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/d7e85c933eecb243cfb49225b4d92c6c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSelbst diese Implementierung k\u00f6nnte potenziell noch weiter beschleunigt werden, indem man AVX-512, Prefetching oder JIT (Just-in-Time-Compiler) f\u00fcr den Anfragenplaner nutzt. Aber das w\u00e4re wirklich ein Thema f\u00fcr einen eigenen Vortrag.<\/p>\n<h2>Probleme mit Bitmap-Indizes<\/h2>\n<p>\nJetzt, da wir bereits die einfache Implementierung des Bitmap-Index in Go und die deutlich leistungsf\u00e4higere Version in Assembler betrachtet haben, lassen Sie uns endlich dar\u00fcber sprechen, warum Bitmap-Indizes so selten verwendet werden.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/83d36a5c92ba90fd680fe8afb6cfc11f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIn \u00e4lteren wissenschaftlichen Arbeiten werden drei Probleme von Bitmap-Indizes erw\u00e4hnt, aber neuere Studien und ich sind der Meinung, dass sie mittlerweile nicht mehr relevant sind. Lassen Sie uns nicht zu tief in jedes dieser Probleme eintauchen, sondern sie nur oberfl\u00e4chlich betrachten.<\/p>\n<h2>Das Problem der hohen Kardinalit\u00e4t<\/h2>\n<p>\nEs wird darauf hingewiesen, dass Bitmap-Indizes nur f\u00fcr Felder mit niedriger Kardinalit\u00e4t geeignet sind, also solche mit wenigen Werten (zum Beispiel Geschlecht oder Augenfarbe). Der Grund daf\u00fcr ist, dass die \u00fcbliche Darstellung solcher Felder (ein Bit pro Wert) bei hoher Kardinalit\u00e4t zu viel Platz ben\u00f6tigen w\u00fcrde und zudem diese Bitmap-Indizes sparsamer (selten) gef\u00fcllt w\u00e4ren.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/0787efc4d2cb4ea4d404ca7888b33697.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/44ab4bc7c25d14fe2f53caf5d9da399d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nManchmal k\u00f6nnen wir eine andere Darstellung verwenden, beispielsweise die Standarddarstellung, die wir zur Darstellung von Zahlen nutzen. Doch genau die Entwicklung von Kompressionsalgorithmen hat alles ver\u00e4ndert. In den letzten Jahrzehnten haben Wissenschaftler und Forscher eine Vielzahl von Kompressionsalgorithmen f\u00fcr Bitmaps entwickelt. Der Hauptvorteil besteht darin, dass es nicht notwendig ist, Bitmaps zu dekomprimieren, um bitweise Operationen durchzuf\u00fchren \u2013 wir k\u00f6nnen bitweise Operationen direkt auf komprimierten Bitmaps ausf\u00fchren.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/ecb54fbf15aa11271bbbab01ecbda880.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIn letzter Zeit sind auch hybride Ans\u00e4tze aufgetaucht, wie beispielsweise Roaring-Bitmaps. Diese nutzen gleichzeitig drei verschiedene Darstellungen f\u00fcr Bitmaps \u2013 n\u00e4mlich die Bitmaps selbst, Arrays und sogenannte Bit Runs \u2013 und balancieren zwischen ihnen, um die Leistung zu maximieren und den Speicherverbrauch zu minimieren.<\/p>\n<p>Roaring-Bitmaps finden Sie in vielen beliebten Anwendungen. Es gibt bereits eine gro\u00dfe Anzahl von Implementierungen in verschiedenen Programmiersprachen, darunter mehr als drei f\u00fcr Go.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/de2adfebc431ff48c996247b453f02ae.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEin weiterer Ansatz, der uns helfen kann, mit hoher Kardinalit\u00e4t umzugehen, ist die Gruppierung (Binning). Stellen Sie sich vor, Sie haben ein Feld, das die K\u00f6rpergr\u00f6\u00dfe einer Person repr\u00e4sentiert. Gr\u00f6\u00dfe ist eine Flie\u00dfkommazahl, aber wir Menschen denken nicht in diesen Begriffen. F\u00fcr uns gibt es keinen Unterschied zwischen 185,2 cm und 185,3 cm.<\/p>\n<p>Das bedeutet, wir k\u00f6nnen \u00e4hnliche Werte in Gruppen innerhalb von 1 cm zusammenfassen.<\/p>\n<p>Und wenn wir zudem wissen, dass nur sehr wenige Menschen eine Gr\u00f6\u00dfe von weniger als 50 cm oder mehr als 250 cm haben, k\u00f6nnen wir das Feld mit unendlicher Kardinalit\u00e4t im Grunde genommen in ein Feld mit ungef\u00e4hr 200 Werten umwandeln.<\/p>\n<p>Nat\u00fcrlich k\u00f6nnen wir, wenn n\u00f6tig, eine zus\u00e4tzliche Filterung auch nachtr\u00e4glich vornehmen.<\/p>\n<h2>Das Problem mit der hohen Bandbreite<\/h2>\n<p>\nEin weiteres Problem der Bitmap-Indizes ist, dass deren Aktualisierung sehr kostspielig sein kann.<\/p>\n<p>Datenbanken m\u00fcssen in der Lage sein, Daten zu aktualisieren, w\u00e4hrend potenziell Hunderte anderer Anfragen diese Daten abfragen. Wir ben\u00f6tigen Locks, um Probleme mit gleichzeitigen Datenzugriffen oder anderen Problemen des gemeinsamen Zugriffs zu vermeiden. Wo es einen gro\u00dfen Lock gibt, treten Probleme auf \u2014 Lock-Kontention, wenn dieser Lock zum Flaschenhals wird.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/0ae1bf925542d286f8b7b245c160a35e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDieses Problem kann durch Sharding oder die Verwendung von versionierten Indizes gel\u00f6st oder umgangen werden.<\/p>\n<p>Sharding ist einfach und allgemein bekannt. Sie k\u00f6nnen einen Bitmap-Index auf die gleiche Weise sharden, wie Sie andere Daten shardieren w\u00fcrden. Anstelle eines gro\u00dfen Locks erhalten Sie viele kleine Locks und vermeiden damit Lock-Kontention.<\/p>\n<p>Eine zweite M\u00f6glichkeit zur Probleml\u00f6sung ist die Verwendung versionierter Indizes. Sie k\u00f6nnen eine Kopie des Indexes haben, die Sie f\u00fcr Suchanfragen oder Lesevorg\u00e4nge verwenden, und eine weitere f\u00fcr das Schreiben oder Aktualisieren. In regelm\u00e4\u00dfigen Abst\u00e4nden (zum Beispiel alle 100 ms oder 500 ms) duplizieren Sie diese und tauschen sie aus. Nat\u00fcrlich ist dieser Ansatz nur anwendbar, wenn Ihre Anwendung mit einem leicht verz\u00f6gerten Suchindex arbeiten kann.<\/p>\n<p>Diese beiden Ans\u00e4tze k\u00f6nnen gleichzeitig verwendet werden: Sie k\u00f6nnen einen shardierten versionierten Index haben.<\/p>\n<h2>Komplexere Abfragen<\/h2>\n<p>Das letzte Problem der Bitmap-Indizes ist, dass sie, wie uns gesagt wird, schlecht f\u00fcr komplexere Abfragetypen geeignet sind, wie zum Beispiel Abfragen \"im Intervall\".<\/p>\n<p>Tats\u00e4chlich sind bitweise Operationen wie AND, OR und \u00c4hnliches nicht besonders geeignet f\u00fcr Anfragen wie: \"Zeig mir Hotels mit Preisen zwischen 200 und 300 Dollar pro Nacht\".<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/7bc2e129cad46fb5875c2b3018c39ff7.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEine naive und \u00e4u\u00dferst unkluge L\u00f6sung w\u00e4re es, die Ergebnisse f\u00fcr jeden Dollarwert zu nehmen und sie mit einer bitweisen OR-Operation zu kombinieren.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/b9f8fc7945caa1866f8e0cfa8a04bd98.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEine effizientere L\u00f6sung w\u00e4re die Verwendung von Gruppierungen, zum Beispiel in Gruppen zu je 50 Euro. Dies w\u00fcrde unseren Prozess um das 50-Fache beschleunigen.<\/p>\n<p>Das Problem l\u00e4sst sich jedoch ebenfalls leicht durch eine speziell f\u00fcr diese Art von Anfragen entwickelte Darstellung l\u00f6sen. In wissenschaftlichen Arbeiten wird sie als range-encoded Bitmaps bezeichnet.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/644a420628b21f220a7af1ff15c4031f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIn dieser Darstellung setzen wir nicht einfach ein Bit f\u00fcr einen bestimmten Wert (zum Beispiel 200), sondern kennzeichnen diesen Wert sowie alle Werte dar\u00fcber. 200 und mehr. Das Gleiche gilt f\u00fcr 300: 300 und mehr. Und so weiter.<\/p>\n<p>Mit dieser Darstellung k\u00f6nnen wir solche Suchanfragen beantworten, indem wir den Index nur zweimal durchsuchen. Zuerst erhalten wir eine Liste von Hotels, in denen der Preis unter 300 Euro liegt, und filtern dann diejenigen heraus, bei denen der Zimmerpreis unter 199 Euro liegt. Fertig.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/cc2bb58d7d7a51495c62ec7da81e2d12.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSie werden \u00fcberrascht sein, aber sogar Geosuchen sind mit Bitmap-Indizes m\u00f6glich. Der Trick besteht darin, eine geographische Darstellung zu verwenden, die Ihre Koordinaten mit einer geometrischen Form umgibt. Zum Beispiel S2 von Google. Die Form sollte aus drei oder mehr sich kreuzenden Linien bestehen, die nummeriert werden k\u00f6nnen. So k\u00f6nnen wir unsere Geosuche in mehrere Anfragen nach dem \"Intervall\" (entlang dieser nummerierten Linien) umwandeln.<\/p>\n<h2>Fertige L\u00f6sungen<\/h2>\n<p>\nIch hoffe, ich habe Ihr Interesse geweckt und Sie haben ein weiteres n\u00fctzliches Werkzeug in Ihrem Arsenal. Wenn Sie jemals etwas \u00c4hnliches ben\u00f6tigen, wissen Sie, in welche Richtung Sie schauen sollten.<\/p>\n<p>Allerdings haben nicht alle die Zeit, Geduld und Ressourcen, um Bitmap-Indizes von Grund auf neu zu erstellen. Besonders die fortschrittlicheren, die SIMD nutzen, zum Beispiel.<\/p>\n<p>Zum Gl\u00fcck gibt es einige fertige L\u00f6sungen, die Ihnen helfen k\u00f6nnen.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/817b47cb189a758756b602ec9cf319e1.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h2>Roaring Bitmaps<\/h2>\n<p>\nZun\u00e4chst gibt es die besagte Roaring Bitmaps-Bibliothek, von der ich bereits gesprochen habe. Sie enth\u00e4lt alle erforderlichen Container und Bitoperationen, die Sie ben\u00f6tigen, um einen vollst\u00e4ndigen Bitmap-Index zu erstellen.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/57f61a51485c174666b52dc2063fabe8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nLeider verwenden derzeit keine Go-Implementierungen SIMD, was bedeutet, dass Go-Implementierungen weniger leistungsf\u00e4hig sind als C-Implementierungen beispielsweise.<\/p>\n<h2>Pilosa<\/h2>\n<p>\nEin weiteres Produkt, das Ihnen helfen kann, ist die Datenbank Pilosa, die im Wesentlichen nur Bitmap-Indizes verwendet. Es ist eine relativ neue L\u00f6sung, die jedoch schnell an Beliebtheit gewinnt.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/d3870a979e1e73d093fe5d5e9bb71cd8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nPilosa verwendet Roaring-Bitmaps und erm\u00f6glicht Ihnen, diese zu nutzen, wodurch die zuvor genannten Konzepte wie Gruppierung, rangekodierte Bitmaps und das Konzept von Feldern vereinfacht und erkl\u00e4rt werden.<\/p>\n<p>Lassen Sie uns schnell einen Blick auf ein Beispiel werfen, wie Pilosa zum Beantworten einer Ihnen bereits bekannten Frage verwendet wird.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/dfee7abfd653cc19d9aa8b64c64f3e4e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDas Beispiel \u00e4hnelt stark dem, was Sie zuvor gesehen haben. Wir erstellen einen Client f\u00fcr den Pilosa-Server, erstellen einen Index und die erforderlichen Felder, f\u00fcgen dann Zufallsdaten mit Wahrscheinlichkeiten in unsere Felder ein und f\u00fchren schlie\u00dflich die vertraute Abfrage aus.<\/p>\n<p>Danach verwenden wir NOT im Feld \u201eexpensive\u201c, kreuzen das Ergebnis (oder AND) mit dem Feld \u201eterrace\u201c und dem Feld \u201ereservations\u201c und erhalten schlie\u00dflich das Endergebnis.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/8d66c6d68019c2297b6c15b700f06a3a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIch hoffe sehr, dass in naher Zukunft dieser neue Index-Typ \u2013 Bitmap-Indizes \u2013 auch in Datenbanken wie MySQL und PostgreSQL verf\u00fcgbar sein wird.<br \/>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/7a8e33d576c7fb6376a173ee038b4206.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h2>Fazit<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Bitmap-Indizes in Go: Suche mit atemberaubender Geschwindigkeit\" src=\"\/wp-content\/uploads\/2019\/05\/c62caa9ad6f2d96056c80326f4fa9a0d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nFalls Sie noch nicht eingeschlafen sind, danke. Ich musste viele Themen aufgrund der begrenzten Zeit kurz anrei\u00dfen, aber ich hoffe, dass der Vortrag hilfreich war und vielleicht sogar motivierend.<\/p>\n<p>Es ist gut, \u00fcber Bitmap-Indizes Bescheid zu wissen, auch wenn sie Ihnen gerade nicht n\u00fctzen. Lassen Sie sie ein weiteres Werkzeug in Ihrer Werkzeugkiste sein.<\/p>\n<p>Wir haben verschiedene Tricks zur Leistungssteigerung f\u00fcr Go besprochen sowie die Aspekte, bei denen der Go-Compiler noch Schwierigkeiten hat. Diese Informationen sind absolut wichtig f\u00fcr jeden Go-Programmierer.<\/p>\n<p>Das ist alles, was ich Ihnen mitteilen wollte. Vielen Dank!<br \/>\n<br \/>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/badoo\/blog\/451938\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0441\u0442\u0443\u043f\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u042f \u0432\u044b\u0441\u0442\u0443\u043f\u0438\u043b \u0441 \u044d\u0442\u0438\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u043e\u043c \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u043d\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 GopherCon Russia 2019 \u0432 \u041c\u043e\u0441\u043a\u0432\u0435 \u0438 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u2014 \u043d\u0430 \u043c\u0438\u0442\u0430\u043f\u0435 \u0432 \u041d\u0438\u0436\u043d\u0435\u043c \u041d\u043e\u0432\u0433\u043e\u0440\u043e\u0434\u0435. \u0420\u0435\u0447\u044c \u0432 \u043d\u0451\u043c \u0438\u0434\u0451\u0442 \u043e bitmap-\u0438\u043d\u0434\u0435\u043a\u0441\u0435 \u2014 \u043c\u0435\u043d\u0435\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u043e\u043c, \u0447\u0435\u043c B-tree, \u043d\u043e \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c. \u0414\u0435\u043b\u044e\u0441\u044c \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c. \u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":25469,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-33793","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0441\u0442\u0443\u043f\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u042f \u0432\u044b\u0441\u0442\u0443\u043f\u0438\u043b \u0441 \u044d\u0442\u0438\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u043e\u043c \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u043d\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 GopherCon Russia 2019 \u0432 \u041c\u043e\u0441\u043a\u0432\u0435 \u0438 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u2014 \u043d\u0430 \u043c\u0438\u0442\u0430\u043f\u0435 \u0432 \u041d\u0438\u0436\u043d\u0435\u043c \u041d\u043e\u0432\u0433\u043e\u0440\u043e\u0434\u0435. \u0420\u0435\u0447\u044c \u0432 \u043d\u0451\u043c \u0438\u0434\u0451\u0442 \u043e bitmap-\u0438\u043d\u0434\u0435\u043a\u0441\u0435 \u2014 \u043c\u0435\u043d\u0435\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u043e\u043c, \u0447\u0435\u043c B-tree, \u043d\u043e \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c. \u0414\u0435\u043b\u044e\u0441\u044c \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c. \u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c,\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/bitmap-indeksy-v-go-poisk-na-dikoj-skorosti\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Bitmap-\u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0432 Go: \u043f\u043e\u0438\u0441\u043a \u043d\u0430 \u0434\u0438\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412\u0441\u0442\u0443\u043f\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u042f \u0432\u044b\u0441\u0442\u0443\u043f\u0438\u043b \u0441 \u044d\u0442\u0438\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u043e\u043c \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u043d\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 GopherCon Russia 2019 \u0432 \u041c\u043e\u0441\u043a\u0432\u0435 \u0438 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u2014 \u043d\u0430 \u043c\u0438\u0442\u0430\u043f\u0435 \u0432 \u041d\u0438\u0436\u043d\u0435\u043c \u041d\u043e\u0432\u0433\u043e\u0440\u043e\u0434\u0435. \u0420\u0435\u0447\u044c \u0432 \u043d\u0451\u043c \u0438\u0434\u0451\u0442 \u043e bitmap-\u0438\u043d\u0434\u0435\u043a\u0441\u0435 \u2014 \u043c\u0435\u043d\u0435\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u043e\u043c, \u0447\u0435\u043c B-tree, \u043d\u043e \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c. \u0414\u0435\u043b\u044e\u0441\u044c \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c. \u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c,\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/bitmap-indeksy-v-go-poisk-na-dikoj-skorosti\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:54:42+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:54:42+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Bitmap-Indizes in Go: Suche mit hoher Geschwindigkeit | ProHoster","description":"Einleitende Worte: Ich habe diesen Vortrag auf Englisch auf der Konferenz GopherCon Russland 2019 in Moskau gehalten und auf Russisch bei einem Meetup in Nischni Nowgorod. Es geht um den Bitmap-Index \u2013 weniger verbreitet als der B-Baum, aber nicht weniger interessant. Ich teile die Aufzeichnung meines Vortrags auf der Konferenz auf Englisch und die schriftliche Transkription auf Russisch. Wir werden betrachten,","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/bitmap-indeksy-v-go-poisk-na-dikoj-skorosti","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Bitmap-\u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0432 Go: \u043f\u043e\u0438\u0441\u043a \u043d\u0430 \u0434\u0438\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 | ProHoster","og:description":"\u0412\u0441\u0442\u0443\u043f\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u042f \u0432\u044b\u0441\u0442\u0443\u043f\u0438\u043b \u0441 \u044d\u0442\u0438\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u043e\u043c \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u043d\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 GopherCon Russia 2019 \u0432 \u041c\u043e\u0441\u043a\u0432\u0435 \u0438 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u2014 \u043d\u0430 \u043c\u0438\u0442\u0430\u043f\u0435 \u0432 \u041d\u0438\u0436\u043d\u0435\u043c \u041d\u043e\u0432\u0433\u043e\u0440\u043e\u0434\u0435. \u0420\u0435\u0447\u044c \u0432 \u043d\u0451\u043c \u0438\u0434\u0451\u0442 \u043e bitmap-\u0438\u043d\u0434\u0435\u043a\u0441\u0435 \u2014 \u043c\u0435\u043d\u0435\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u043e\u043c, \u0447\u0435\u043c B-tree, \u043d\u043e \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c. \u0414\u0435\u043b\u044e\u0441\u044c \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c. \u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c,","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/bitmap-indeksy-v-go-poisk-na-dikoj-skorosti","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:54:42+00:00","article:modified_time":"2019-10-31T18:54:42+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"33793","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 16:43:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:33:25","updated":"2026-01-21 16:43:19"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/33793","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=33793"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/33793\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/25469"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=33793"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=33793"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=33793"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}