SQL SELECT Geschwindigkeit int vs varchar


110

Ich bin gerade dabei, eine Tabelle zu erstellen, und ich habe mich gefragt.

Wenn ich Autos mit einer Marke speichere (z. B. BMW, Audi usw.), hat dies einen Einfluss auf die Abfragegeschwindigkeit, wenn ich die Marke als int oder varchar speichere.

So ist es auch

SELECT * FROM table WHERE make = 5 AND ...;

Schneller / langsamer als

SELECT * FROM table WHERE make = 'audi' AND ...;

oder wird die Geschwindigkeit mehr oder weniger gleich sein?

Antworten:


99

Int-Vergleiche sind schneller als Varchar-Vergleiche, da Ints viel weniger Platz beanspruchen als Varchars.

Dies gilt sowohl für nicht indizierten als auch für indizierten Zugriff. Der schnellste Weg ist eine indizierte int-Spalte.


Wie ich sehe, haben Sie die Frage postgreql markiert. Möglicherweise interessieren Sie sich für die Speicherplatznutzung verschiedener Datumstypen:


13
Sie beziehen sich auf Seite 7.4. In modernen Versionen nehmen sie 1 Byte + Länge ein, wenn Sie <126 Bytes haben. Beachten Sie auch, dass der Grund dafür, dass Zeichenfolgen viel langsamer sind, häufig darin besteht, dass der Vergleich der Kollatierung sehr teuer ist - nicht, dass die Zeichenfolge mehr Platz beansprucht. Aber das Endergebnis ist natürlich das gleiche.
Magnus Hagander

@Magnus - danke für das Heads-up. Fühlen Sie sich frei, meine Antwort zu bearbeiten, da ich sehe, dass Sie genug Wiederholungspunkte haben.
Robert Munteanu

"nicht, dass die Zeichenfolge mehr Platz beansprucht" ... Zeichenfolgen über minimalen Größen nehmen viel mehr Platz ein als selbst hochpräzise Zahlen, da eine Zahl (Singular) eine feste Einheit hat. Zeichenfolgen sind immer aggregierte Typen . 8 Bytes für eine 64-Bit-Nummer 4 Bytes pro Zeichen in einer Zeichenfolge, einschließlich entweder eines Längenbytes oder einer Struktur; oder ein anderes Abschlusszeichen für unglaublich naive Implementierungen ...
MrMesees

@RobertMunteanu Hey Robert, entschuldige, ich weiß, dass dies ein alter Beitrag ist, aber kann ich bitte Folgendes überprüfen: Um Ganzzahlen abzufragen, muss ich jede Zeichenfolgenspalte mit einer anderen Tabelle (Beziehung) verknüpfen. Dies bedeutet jedoch, dass für jede Abfrage mehr Verknüpfungsvorgänge erforderlich sind. Wie bestimme ich, ob sich dieser Kompromiss lohnt? Danke dir!
AiRiFiEd

2
"Int-Vergleiche sind schneller als Varchar-Vergleiche, weil Ints viel weniger Platz beanspruchen als Varchars" - dies gilt im Allgemeinen NICHT . Abhängig vom verwendeten DBMS und den genauen Datentypen und Zeichenfolgen, die Sie einfügen möchten, kann es sein, dass Ihre (sagen wir) 8-Byte-Ints länger sind als ASCII-Varchars, die einige Text-IDs mit einer durchschnittlichen Länge von 3-4 Zeichen enthalten. Diese Antwort - ungenau zu sein und keinen spezifischen Kontext oder experimentelle Ergebnisse zu haben - beantwortet die Frage also nicht wirklich. Jeder weiß, dass Varchare viel mehr Platz beanspruchen dürfen als Ints, aber das müssen sie NICHT.
Marcin Wojnarski

36

Einige grobe Benchmarks:

4 Millionen Datensätze in Postgres 9.x.

Table A = base table with some columns
Table B = Table A + extra column id of type bigint with random numbers
Table C = Table A + extra column id of type text with random 16-char ASCII strings

Ergebnisse auf 8 GB RAM, i7, SSD-Laptop:

Size on disk:                A=261MB        B=292MB        C=322MB
Non-indexed by id: select count(*), select by id: 450ms same on all tables
Insert* one row per TX:       B=9ms/record        C=9ms/record
Bulk insert* in single TX:    B=140usec/record    C=180usec/record
Indexed by id, select by id:  B=about 200us       C=about 200us

* inserts to the table already containing 4M records

So wie es für dieses Setup aussieht, macht Bigint im Vergleich zu 16-stelligem Text keinen Unterschied in der Geschwindigkeit, solange Ihre Indizes in den Arbeitsspeicher passen.


6
Sehr interessant. Wie kommt es, dass der Unterschied vernachlässigbar ist?
Chibueze Opata

18

Mit einem int anstelle eines varchar wird es etwas schneller. Wichtiger für die Geschwindigkeit ist es, einen Index für das Feld zu haben, mit dem die Abfrage die Datensätze finden kann.

Es gibt einen weiteren Grund, ein int zu verwenden, nämlich die Datenbank zu normalisieren. Anstatt den Text 'Mercedes-Benz' tausende Male in der Tabelle zu speichern, sollten Sie seine ID speichern und den Markennamen einmal in einer separaten Tabelle speichern.


Könnten Sie mehr erklären? Meinen Sie, anstatt Mercedes-Benztausende Male ID zu speichern 1. Zum Beispiel Tabelle car_brands, Spalten Brandsund Id. Reihe Mercedes-Benzund 1. Und in der Spalte Brandsund im Wert der Haupttabelle 1. Und wann SELECT, dann zuerst Idvom Tisch car_brandsund dann SELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz). Oder ein anderer Ansatz?
Andris

3
@ user2118559: Ja, so würden Sie es speichern. Um die Daten abzurufen, verwenden Sie im Allgemeinen einen Join anstelle einer Unterabfrage : select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz'.
Guffa

Warum das Downvote? Wenn Sie nicht erklären, was Sie für falsch halten, kann dies die Antwort nicht verbessern.
Guffa

8

In diesem Fall spielt es keine Rolle, ob die Größe des Zeichenfolgenvergleichs im Vergleich zu Nicht-Floats vorliegt oder nicht. Größe ist eigentlich der wahre Leistungsunterschied. Sei es 1 Byte + (bis zu 126 Byte) im Vergleich zu 1,2,4 oder 8 Byte Vergleich ... offensichtlich sind Nicht-Float kleiner als Strings und Floats und daher CPU-freundlicher in der Montage.

Der Vergleich von Zeichenfolgen zu Zeichenfolgen in allen Sprachen ist langsamer als etwas, das von der CPU in einem Befehl verglichen werden kann. Selbst der Vergleich von 8 Byte (64 Bit) auf einer 32-Bit-CPU ist immer noch schneller als ein VARCHAR (2) oder größer. * Schauen Sie sich noch einmal die produzierte Baugruppe an (auch von Hand). Es sind mehr Anweisungen erforderlich, um char by char zu vergleichen, als 1 bis 8 Byte CPU-Zahlen.

Wie viel schneller? hängt auch vom Datenvolumen ab. Wenn Sie einfach 5 mit 'audi' vergleichen - und das ist alles, was Ihre Datenbank hat, ist der resultierende Unterschied so gering, dass Sie ihn niemals sehen würden. Abhängig von der CPU, der Implementierung (Client / Server, Web / Skript usw.) wird es wahrscheinlich erst angezeigt, wenn Sie einige hundert Vergleiche auf dem DB-Server durchgeführt haben (möglicherweise sogar ein paar tausend Vergleiche, bevor es auffällt).

  • Um den falschen Streit über Hash-Vergleiche aufzuheben. Die meisten Hashing-Algorithmen selbst sind langsam, sodass Sie nicht von Dingen wie CRC64 und kleiner profitieren. Über 12 Jahre lang habe ich Suchalgorithmen für Suchmaschinen mit mehreren Landkreisen und 7 Jahre für die Kreditauskunfteien entwickelt. Alles, was Sie numerisch halten können, ist schneller ... zum Beispiel Telefonnummern, Postleitzahlen, sogar Währung * 1000 (Speicher) Währung div 1000 (Abruf) ist für Vergleiche schneller als DECIMAL.

Ozz


6

Index oder nicht, int ist viel schneller (je länger der Varchar, desto langsamer wird er).

Ein weiterer Grund: Der Index für das Varchar-Feld ist viel größer als für Int. Bei größeren Tabellen kann dies Hunderte von Megabyte (und Tausende von Seiten) bedeuten. Dies macht die Leistung erheblich schlechter, da das Lesen des Index allein viele Festplattenlesevorgänge erfordert.


3
Würde der Index beispielsweise bei 5 Millionen Datensätzen von "audi" nicht nur eine Kopie der Zeichenfolge von "audi" und 5 Millionen Ganzzahlen von primary_key enthalten? Wäre der Größenunterschied wirklich so groß, sei es vchar oder integer?
Lulalala

Sie haben Recht, Lulalala, aber für eine Spalte, die zufällige Zeichenfolgen enthalten wird, ist die Antwort fair genug.
Awais Fiaz

4

Im Allgemeinen wird der int schneller sein. Je länger der Varchar ist, desto langsamer wird er


3

Hinweis: Wenn die möglichen Werte für das Feld machen werden nie (oder selten) ändern, Sie ENUM als Kompromiss verwenden können. Es kombiniert gute Geschwindigkeit mit guter Lesbarkeit.


1
Interessant, wie wird der Geschwindigkeitsunterschied zwischen ENUM und int sein?
Googletorp

Hat PostgresSQL einen enumDatentyp? Ich dachte, es war MySQL-spezifisch.
Robert Munteanu

Postgres hat ENUM, aber ich denke nicht, dass es genauso implementiert ist wie MySQL. postgresql.org/docs/current/static/datatype-enum.html
googletorp

2
In Bezug auf die Leistung sollte ENUM mehr oder weniger die gleiche Leistung wie int im Suchfeld aufweisen, jedoch als varchar in der Zielliste (da die gesamte Zeichenfolge für übereinstimmende Zeilen an den Client übertragen werden muss, nicht nur für int)
Magnus Hagander

1
Hier eine interessante Lektüre darüber, warum man in MySQL KEINE Enumeration verwenden sollte (nur um dem Feuer etwas Treibstoff hinzuzufügen: D)
Wilt

1

Wenn Sie die Indizierung für eines der Felder aktivieren, ist dies schneller. Was deine Frage betrifft, denke ich intist schneller als varchar.


0

Etwas relativ. Ja, INTs werden schneller sein, aber die Frage ist, ob es in Ihrer Situation auffällt. Sind die VARCHARs nur ein paar kleine Wörter oder längere Texte? und wie viele Zeilen enthält die Tabelle? Wenn es nur wenige Zeilen gibt, wird es höchstwahrscheinlich vollständig im Speicher gepuffert (wenn dies häufig angefordert wird). In diesem Fall werden Sie keinen großen Unterschied bemerken. Dann gibt es natürlich eine Indizierung, die wichtiger wird, wenn die Tabelle wächst. Die Verwendung von SSDs ist möglicherweise schneller als HDs mit optimierten Abfragen. Auch gute Festplattencontroller beschleunigen manchmal Abfragen> 10x. Dies lässt möglicherweise Platz für die Verwendung von VARCHARs, was das Lesen und Schreiben von Abfragen erleichtert (es müssen keine komplexen Verknüpfungen geschrieben werden) und die Entwicklung beschleunigt. Puristen werden jedoch nicht zustimmen und immer alles normalisieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.