RFZ: SELECT auf einzelne bytes in BINARY(N)

Grüße,
ich habe eine mySQL Tabelle mit einer Spalte "data" vom Typ BINARY(127) und würde jetzt gerne die Bytes 0-3 von den Zeilen selektieren, bei denen Byte 2 = 0x88 ist.
Wie macht man das?

SELECT  
	HEX(SUBSTR(data,1,1)),  
	HEX(SUBSTR(data,2,1)),  
	HEX(SUBSTR(data,3,1)),  
	HEX(SUBSTR(data,4,1))  
FROM  
	raw  
WHERE  
	HEX(SUBSTR(data,3,1)) = HEX(0x88)

Das tut zwar, aber sieht unschön aus und ist auch recht umständlich. Geht das eleganter?
Ausserdem ist ein Index auf der Spalte - wird der mit SUBSTR() noch korrekt genutzt?

Wie sieht es aus, wenn ich die Bytes 0 und 1 zusammen gerne als 16 bit Integer selektieren wollen würde?

Danke :)

  1. Tach!

    ich habe eine mySQL Tabelle mit einer Spalte "data" vom Typ BINARY(127) und würde jetzt gerne die Bytes 0-3 von den Zeilen selektieren, bei denen Byte 2 = 0x88 ist.
    Wie macht man das?

    SELECT

    HEX(SUBSTR(data,1,1)),
    HEX(SUBSTR(data,2,1)),
    HEX(SUBSTR(data,3,1)),
    HEX(SUBSTR(data,4,1))
    FROM
    raw
    WHERE
    HEX(SUBSTR(data,3,1)) = HEX(0x88)

    
    >   
    > Das tut zwar, aber sieht unschön aus und ist auch recht umständlich. Geht das eleganter?  
      
    Nicht dass ich wüsste. In der SELECT-Klausel vielleicht, wenn du die Bytes nicht einzeln sondern am Stück zurückgibst und im abfragenden Programm auseinandernimmst.  
      
    
    > Ausserdem ist ein Index auf der Spalte - wird der mit SUBSTR() noch korrekt genutzt?  
      
    Sicher nicht. Ein Index ist eine sortierte Menge. Nur so kann man in ihr schnell etwas finden. Du hast garantiert nicht angegeben, dass der Index für Byte x angelegt werden soll, weil das syntaktisch gar nicht vorgesehen ist.  
      
    EXPLAIN kann dir Fragen zum verwendeten Index genau beantworten. Bei zu wenig Daten in der Tabelle wird allerdings auch gern mal kein Index verwendet, weil das zusätzliche Lesen des Index sonst länger dauert als das direkte lesen der Daten. Das entscheidet der Optimizer von Fall zu Fall.  
      
    
    > Wie sieht es aus, wenn ich die Bytes 0 und 1 zusammen gerne als 16 bit Integer selektieren wollen würde?  
      
    MySQL hat im Handbuch eine Übersicht zu allen Funktionen. Wenn du da was passendes findest ...  
      
      
    dedlfix.
    
    1. Moin

      Nicht dass ich wüsste. In der SELECT-Klausel vielleicht, wenn du die Bytes nicht einzeln sondern am Stück zurückgibst und im abfragenden Programm auseinandernimmst.

      das abfragende Programm bin ich - ich mache einfach Auswertungen über die Datenmenge und würde gerne auf weiteren Programmcode verzichten...

      EXPLAIN kann dir Fragen zum verwendeten Index genau beantworten.

      Danke, schaue ich mir mal an

      MySQL hat im Handbuch eine Übersicht zu allen Funktionen. Wenn du da was passendes findest ...

      Habe ich natürlich gemacht, aber ausser SUBSTR() sehe ich nichts um an einzelne Bytes zu kommen, die dann als STRING bereit stehen. Danach braucht es zwangsweise ein HEX(), ASCII() oder CONVERT() um mit den Daten was anfangen zu können. Das ist etwas schade. Mehr habe ich nicht gefunden.

      Noch jemand Ideen?

      Wenn ich für jedes Byte eine Spalte anlege und die Bytes als 8 Bit INT anlege, dann geht es schon eleganter, vor allem mit Binäroperationen:

      SELECT  
          HEX(Byte00),  
          HEX(Byte01),  
          HEX(Byte02),  
          HEX(Byte03),  
          (Byte00 << 8)|Byte01  
      FROM  
          data  
      WHERE  
          Byte02 = 0x88
      

      Aber ist das der bessere Weg?

      1. Moin
        Noch jemand Ideen?

        Ein Index greift nur, wenn die Bytesequenz in WHERE exakt mit der Bytesequenz im Feld übereinstimmt.

        Wenn ich für jedes Byte eine Spalte anlege

        Das wäre die logische Konsequenz aus dem Wunsch heraus, einen Index nutzen zu wollen.

        Wie sieht es aus, wenn ich die Bytes 0 und 1 zusammen gerne als 16 bit Integer selektieren wollen würde?

        Das sieht für mich so aus, als könnte auch die Datenerfassung optimiert werden.

        MfG

  2. Liebe Mitdenker,
    liebe Wissende,
    liebe Neugierige,

    ja!

    ich habe eine mySQL Tabelle mit einer Spalte "data" vom Typ BINARY(127) und würde jetzt gerne die Bytes 0-3 von den Zeilen selektieren, bei denen Byte 2 = 0x88 ist.
    Wie macht man das?

    SELECT

    HEX(SUBSTR(data,1,1)),
    HEX(SUBSTR(data,2,1)),
    HEX(SUBSTR(data,3,1)),
    HEX(SUBSTR(data,4,1))
    FROM
    raw
    WHERE
    HEX(SUBSTR(data,3,1)) = HEX(0x88)

    
    >   
    > Das tut zwar, aber sieht unschön aus und ist auch recht umständlich. Geht das eleganter?  
    > Ausserdem ist ein Index auf der Spalte - wird der mit SUBSTR() noch korrekt genutzt?  
    >   
    > Wie sieht es aus, wenn ich die Bytes 0 und 1 zusammen gerne als 16 bit Integer selektieren wollen würde?  
      
    Ich frag nur mal aus Neugier:  
    Was hast Du vor mit der Teillösung?  
      
    Ein Index über eine (Var)Binary-Spalte wird bis maximal 1000 Bytes Breite des Index geführt (MySQL 5.5) und auch verwendet, solange der Optimizer erkennen kann, dass dies einen Vorteil bietet. Bei Zugriff auf Werte, die nicht "vorne" beginnen, ist dies nicht möglich, da die gar nicht in den Index aufgenommen worden sind.  
      
    Es bietet sich an, sich Datenbankfunktionen für die Zugriffe und Selektionen zu erstellen, deren Rückgabeergebnisse auf die verwendete API angepasst sind. Da muss man eventuell dann die interne Darstellung (Little-Endian / Big-Endian) berücksichtigen.  
      
      
      
      
    Spirituelle Grüße  
    Euer Robert
    
    -- 
    Möge der Forumsgeist wiederbelebt werden!
    
    1. Grüße

      Was hast Du vor mit der Teillösung?

      mir geht es darum, Abfragen über eine gegebene Datenmenge zu machen, um etwas mehr über ihre Struktur zu erfahren. Daher ist auch vorab nicht definiert, welche Bytes ich genau wie selektiere, da ich die Daten garnicht in und auswendig kenne.

      Mir geht es um so Fragen wie "Wie ist die Werteverteilung des Byte Y wenn Byte X = A ist?" ...

      Ein Index über eine (Var)Binary-Spalte wird bis maximal 1000 Bytes Breite des Index geführt (MySQL 5.5) und auch verwendet, solange der Optimizer erkennen kann, dass dies einen Vorteil bietet. Bei Zugriff auf Werte, die nicht "vorne" beginnen, ist dies nicht möglich, da die gar nicht in den Index aufgenommen worden sind.

      Danke, die Info ist hilfreich, da dann der Index vermutlich kaum was bringt aber viel Platz fressen dürfte...

      Es bietet sich an, sich Datenbankfunktionen für die Zugriffe und Selektionen zu erstellen, deren Rückgabeergebnisse auf die verwendete API angepasst sind. Da muss man eventuell dann die interne Darstellung (Little-Endian / Big-Endian) berücksichtigen.

      Danke, aber eine verwendete API gibt es nicht ;)

      Ich glaube ich fahre tatsächlich besser wenn ich mir jedes Byte in eine Spalte lege und auf die die ich häufiger selektiere einen Index baue....