Heim  >  Artikel  >  Datenbank  >  Detaillierte Erläuterung der Index- und FROM_UNIXTIME-Probleme in MySQL

Detaillierte Erläuterung der Index- und FROM_UNIXTIME-Probleme in MySQL

小云云
小云云Original
2018-01-17 10:45:081829Durchsuche

Dieser Artikel stellt hauptsächlich die relevanten Informationen zum Index und zu FROM_UNIXTIME-Problemen in MySQL vor. Ich hoffe, dass er allen helfen kann.

Null und Hintergrund

Nachdem ich einfach ein paar Informationen gesammelt hatte, stellte ich fest, dass dieses langsame Abfrageproblem tief im Verborgenen liegt. Nachdem ich viele Leute gefragt hatte, einschließlich des DBA, habe ich es immer noch nicht getan Ich kenne den Grund nicht.

1. Problem

Es gibt eine Datenbank mit einem wie folgt definierten Feld.


MySQL [d_union_stat]> desc t_local_cache_log_meta;
+----------------+--------------+------+-----+---------------------+
| Field     | Type     | Null | Key | Default       |
+----------------+--------------+------+-----+---------------------+
| c_id      | int(11)   | NO  | PRI | NULL        |
| c_key     | varchar(128) | NO  | MUL |           |
| c_time     | int(11)   | NO  | MUL | 0          |
| c_mtime    | varchar(45) | NO  | MUL | 0000-00-00 00:00:00 |
+----------------+--------------+------+-----+---------------------+
17 rows in set (0.01 sec)

Der Index lautet wie folgt:


MySQL [d_union_stat]> show index from t_local_cache_log_meta \G     
*************************** 1. row ***************************
    Table: t_local_cache_log_meta
  Non_unique: 0
   Key_name: PRIMARY
 Column_name: c_id
  Collation: A
 Cardinality: 6517096
  Index_type: BTREE
*************************** 2. row ***************************
.
.
.
*************************** 6. row ***************************
    Table: t_local_cache_log_meta
  Non_unique: 1
   Key_name: index_mtime
 Column_name: c_mtime
  Collation: A
 Cardinality: 592463
  Index_type: BTREE
6 rows in set (0.02 sec)

Dann habe ich eine SQL wie folgt geschrieben:


SELECT 
  count(*)
FROM
  d_union_stat.t_local_cache_log_meta
where
  `c_mtime` < FROM_UNIXTIME(1494485402);

Eines Tages kam schließlich der DBA vorbei und gab mir einen Bericht, in dem er sagte, dass es sich bei diesem SQL um langsames SQL handele.


# Time: 170518 11:31:14
# Query_time: 12.312329 Lock_time: 0.000061 Rows_sent: 0 Rows_examined: 5809647
SET timestamp=1495078274;
DELETE FROM `t_local_cache_log_meta` WHERE `c_mtime`< FROM_UNIXTIME(1494473461) limit 1000;
Ich war sprachlos und SQL ist sorgfältig optimiert.

Auf die Frage, warum SQL langsam ist, konnte der DBA keine Antwort geben. Selbst die Kollegen um mich herum konnten keine Antwort geben.

Ich dachte insgeheim, ich sei auf einen tief verborgenen Wissenspunkt gestoßen.

Es gibt zwei verdächtige Aspekte: 1. Es gibt 6 Indizes. 2. Der R-Wert ist die FROM_UNIXTIME-Funktion.

Also habe ich die offizielle MYSQL-Dokumentation überprüft und festgestellt, dass 6 kein Problem darstellt.


Alle Speicher-Engines unterstützen mindestens 16 Indizes pro Tabelle und eine Gesamtindexlänge von mindestens 256 Bytes

Die meisten Speicher-Engines haben höhere Grenzwerte.

Ich vermute also, dass Das Problem ist die FROM_UNIXTIME-Funktion.

Dann schauen Sie sich den INDEX-Bereich von MYSQL an und finden Sie einige Hinweise.


Um schnell die Zeilen zu finden, die einer WHERE-Klausel entsprechen.

2. Um Zeilen aus der Betrachtung auszuschließen.
Wenn die Wahl zwischen mehreren Indizes besteht, verwendet MySQL normalerweise den Index findet die kleinste Anzahl von Zeilen.
3. Wenn die Tabelle einen mehrspaltigen Index hat, kann der Optimierer jedes Präfix ganz links zum Nachschlagen von Zeilen verwenden effizienter, wenn sie den gleichen Typ und die gleiche Größe haben. Der Vergleich unterschiedlicher Spalten (zum Beispiel der Vergleich einer Zeichenfolgenspalte mit einer zeitlichen oder numerischen Spalte) kann die Verwendung von Indizes verhindern, wenn Werte nicht direkt ohne Konvertierung verglichen werden können .

Als ich Artikel 4 sah, wurde erwähnt, dass unterschiedliche Typen zu keiner Indizierung führen können. Könnte es sein, dass der Rückgabewert von FROM_UNIXTIME nicht in einen String-Typ konvertiert werden kann?

Fragen Sie also den Rückgabewert der Funktion FROM_UNIXTIME ab.


gibt einen Zeittyp zurück. Wie wäre es also, ihn auf einen String-Typ zu zwingen? MySQL FROM_UNIXTIME() returns a date /datetime from a version of unix_timestamp.



Sie können dieses Mal sehen, dass der Index verwendet wird und nur ein Datenelement gescannt wird.

MySQL [d_union_stat]> explain SELECT 
  ->   *
  -> FROM
  ->   t_local_cache_log_meta
  -> where
  ->   `c_mtime` = CONCAT(FROM_UNIXTIME(1494485402)) \G
*************************** 1. row ***************************
      id: 1
 select_type: SIMPLE
    table: t_local_cache_log_meta
     type: ref
possible_keys: index_mtime
     key: index_mtime
   key_len: 137
     ref: const
     rows: 1
    Extra: Using where
1 row in set (0.01 sec)

2. Fazit

Dieses Mal können Sie den Index verwenden, indem Sie die Konvertierung des Rückgabewerts von FROM_UNIXTIME erzwingen.

Daher kann diese SQL den oberen Index nicht verwenden, da die Typen von R-Werten und L-Werten inkonsistent sind. .

Verwandte Empfehlungen:


So erstellen Sie einen Index für eine Join-Tabelle, die sich auf zwei Tabellen in MySQL bezieht. Detaillierte Grafik- und Texterklärung

MySQL-Partitionsfeld Ist es notwendig, einen separaten Index für die Spalte zu erstellen?

Einführung in die Methode zum Anzeigen, Erstellen und Löschen von Indizes in MySQL

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Index- und FROM_UNIXTIME-Probleme in MySQL. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn