ThinkPHP5 verfügt über eine integrierte Partitionsmethode, mit der einfache Tabellenpartitionen implementiert werden können. Wenn Sie einzelne Daten hinzufügen, ändern, löschen oder abfragen, können Sie problemlos die Partitionsmethode verwenden, da diese Vorgänge eine gemeinsame Funktion haben: Sie können im Voraus genau wissen, welchen Datensatz Sie bearbeiten möchten. Es besteht jedoch ein Bedarf, den ThinkPHP5 nicht zu lösen scheint. Wenn beispielsweise eine große Tabelle in mehrere Untertabellen aufgeteilt wird, müssen Paging-Daten basierend auf relevanten Bedingungen und Sortierung abgerufen werden.
Da wir in diesem Nachfrageszenario nicht im Voraus wissen, welche Daten auf der ersten Seite und welche auf der zweiten Seite angezeigt werden, wie werden die Listendaten abgefragt, die entsprechend dynamisch abgeglichen werden? Suchbedingungen?
Ein gescheiterter Versuch
Der erste und direkteste Weg, der mir in den Sinn kommt, ist die Kombination der Partitionsmethode und der Paginierungsmethode. Das Ergebnis war tragisch , und die Datenbank stürzte direkt ab. Der Grund dafür ist, dass die Partitionsmethode zum Implementieren einer Paging-Abfrage mehrere Untertabellen vereinigen muss und die Untertabellen jeder Vereinigung die Form „select *“ haben, was die Effizienz der Abfrage erheblich beeinträchtigt. beim Abrufen von Datensätzen Bei der Berechnung der Gesamtzahl ist eine Abfrage aller Felder absolut nicht erforderlich.
Der Weg zum Erfolg
Da sich select * auf die Effizienz auswirkt, was passiert, wenn der Primärschlüssel ausgewählt wird? Natürlich geht es ziemlich schnell! Die allgemeine Idee besteht darin, Daten in zwei Schritten abzurufen. Das erste Mal besteht darin, den Primärschlüssel abzufragen, und das zweite Mal besteht darin, die entsprechenden Daten basierend auf dem Primärschlüssel abzurufen. Die spezifische Implementierung lautet wie folgt:
Kernidee
Nach der horizontalen Aufteilung der Tabelle wird die Effizienz sehr gering, wenn Daten in Seiten abgerufen werden müssen Wenn mehr Untertabellen aufgeteilt werden, ist die Auswirkung auf die Abfrageleistung größer. Die Kernidee besteht also darin, zu versuchen, den entsprechenden Datensatz über die Primärschlüssel-ID abzurufen, dh die Listendaten zweimal abzurufen.
1. Fragen Sie zunächst die Gesamtzahl der Datensätze und die Primärschlüssel-ID ab.
In diesem Schritt müssen Sie in der SELECT-Anweisung der Union-Untertabelle nur die Primärschlüssel-ID und auflisten weitere zusätzliche Pflichtfelder. Die relevanten Felder müssen nicht vorhanden sein.
2. Fragen Sie die entsprechenden vollständigen Daten basierend auf der Primärschlüssel-ID ab.
Funktionskapselung
1. Erstellen Sie eine SQL-Unterabfrageanweisung, um die Gesamtzahl der Datensätze und die Primärschlüssel-ID zu erhalten
/** * 构造获取总记录数及主键ID的sql子查询语句 * @param $table 主表名称 * @param $idKey 主键id字段名称 * @param string $fields 其它字段名称,多个字段用英文逗号分隔 * @param int $num 子表数量 * @param string $where 查询条件 * @return array */ function buildPartitionSql($table,$idKey,$fields='',$num=1,$where='') { $countTable = []; $listTable = []; $fieldList = [$idKey]; if ($fields) { $fieldList = array_merge($fieldList,explode(',',$fields)); $fieldList = array_unique($fieldList); } $fieldStr = implode(',',$fieldList); for ($i = 0; $i < $num; $i++) { $countTable[] = sprintf('SELECT %s FROM %s_%s where 1=1 %s', $idKey, $table, ($i + 1), $where); $listTable[] = sprintf('SELECT %s FROM %s_%s where 1=1 %s', $fieldStr,$table, ($i + 1), $where); } $countTable = '( ' . implode(" UNION ", $countTable) . ') AS ' . $table; $listTable = '( ' . implode(" UNION ", $listTable) . ') AS ' . $table; $tables = ['countSql' => $countTable, 'listSql' => $listTable]; return $tables; }
Aufrufmethode:
Angenommen, das Ausführungsergebnis der Funktion buildPartitionSql ist $tables, dann lautet die vollständige SQL-Anweisung wie folgt:
Holen Sie sich die vollständige SQL der Gesamtzahl der Datensätze:
select count(1) as total from .$tables['countSql']
Holen Sie sich die vollständige SQL der Primärschlüssel-ID:
select * from .$tables['listSql']. limit 0,10
2. Erstellen Sie eine SQL-Unterabfrageanweisung, um den Datensatz zu erhalten, der der angegebenen ID entspricht
/** * 构造获取指定id对应记录的sql子查询语句 * @param $table 主表名称 * @param $idKey 指定的id字段名称 * @param $idValues 指定的id字段值 * @param int $num 子表数量 * @return string */ function buildPartitionListSql($table,$idKey,$idValues,$num=1) { $sql = ''; $ids = is_array($idValues) ? implode(',',$idValues) : $idValues; if ($ids) { $listTable = []; for ($i = 0; $i < $num; $i++) { $listTable[] = sprintf('SELECT * FROM %s_%s where %s in (%s)', $table, ($i + 1), $idKey, $ids); } $sql = '( ' . implode(" UNION ", $listTable) . ') AS ' . $table; } return $sql; }
Aufrufmethode:
Angenommen Wenn das Ausführungsergebnis der Funktion buildPartitionListSql $sql ist, lautet die vollständige SQL-Anweisung wie folgt:
select * from .$sql
Hinweis: Alle Suchbedingungen auf Geschäftsebene werden in der Union-Klausel des ersten Schritts platziert Im zweiten Schritt müssen Sie nur die Daten basierend auf der ID abrufen.
php Chinesische Website, eine große Anzahl kostenloser thinkphp-Einführungs-Tutorials, willkommen zum Online-Lernen!
Das obige ist der detaillierte Inhalt vonThinkPHP5-Paging-Abfragelösung nach horizontaler Tabellenaufteilung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!