Die Abfrage einer MySQL-Datenbank dauert eine gewisse Zeit
P粉764836448
2023-08-31 22:29:19
<p>Ich habe eine große Nachrichtendatenbank mit 24.000 Zeilen:</p>
<pre class="brush:php;toolbar:false;">Zeigt die Zeilen 0–24 an (insgesamt 2455455 Zeilen, die Abfrage dauert 0,0006 Sekunden). </pre>
<p> Nachrichten, daher muss ich Konversationen schneller laden. Für Benutzer mit weniger Konversationen erfolgt das Laden wie folgt (Benutzer hat 3,2.000 Konversationen): </p>
<pre class="brush:php;toolbar:false;">Zeile 0-24 anzeigen (insgesamt 3266 Zeilen, Abfrage dauert 0,0345 Sekunden) [id: 5009666... - 4375619...]. </pre>
<p>Langsamerer Ladevorgang für Benutzer mit vielen Konversationen (Benutzer mit 40.000 Konversationen): </p>
<pre class="brush:php;toolbar:false;">Zeile 0-24 anzeigen (insgesamt 40296 Zeilen, Abfrage dauert 5,1763 Sekunden) [id: 5021561... - 5015545...]. </pre>
<p>Ich verwende Indexschlüssel für diese Spalten: </p>
<pre class="brush:php;toolbar:false;">id, to_id, from_id, time, seen</pre>
<p>Datenbanktabelle: </p>
<pre class="brush:php;toolbar:false;">CREATE TABLE `messages` (
`id` int(255) NICHT NULL,
`to_id` int(20) NICHT NULL,
`from_id` int(20) NICHT NULL,
„Nachricht“-Langtext NICHT NULL,
„time“ double NICHT NULL,
`seen` int(2) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `messages` (`id`, `to_id`, `from_id`, `message`, `time`, `seen`) VALUES
(2, 6001, 2, „Hallo“, 1587581995.5222, 1);
ALTER TABLE „Nachrichten“.
PRIMÄRSCHLÜSSEL („id“) HINZUFÜGEN,
SCHLÜSSEL „time_idx“ („time“) HINZUFÜGEN,
SCHLÜSSEL `from_idx` (`from_id`) HINZUFÜGEN,
SCHLÜSSEL `to_idx` (`to_id`) HINZUFÜGEN,
SCHLÜSSEL „seenx“ („seen“) HINZUFÜGEN,
SCHLÜSSEL `idx` (`id`) HINZUFÜGEN;
ALTER TABLE „Nachrichten“.
MODIFY `id` int(255) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5021570;
COMMIT;</pre>
<p>Ich verwende die folgende Abfrage: </p>
<pre class="brush:php;toolbar:false;">SELECT
*
AUS
Mitteilungen,
(
WÄHLEN
MAX(id) als letzte ID
AUS
Mitteilungen
WO
(
message.to_id = '1' – die ID, mit der verglichen werden soll (die ID des angemeldeten Benutzers)
ODER message.from_id = '1' – die ID, mit der verglichen werden soll (die ID des angemeldeten Benutzers)
)
GRUPPIERE NACH
CONCAT(
MINDESTENS(messages.to_id, messages.from_id),
'.',
GREATEST(messages.to_id, messages.from_id)
)
) als Gespräche
WO
id = Gespräche.lastid
SORTIEREN NACH
message.id DESC</pre>
<p>Ich weiß nicht, wie ich es für Benutzer mit vielen Konversationen schneller machen kann, wenn ich die Datenbankstruktur neu erstellen soll. </p>
嗯,也许你可以尝试为你的表添加索引:https://www.drupal.org/docs/7/guidelines-for-sql/the-benefits-of-indexing-large-mysql-tables#:~:text=Creating%20Indexes&text=The%20statement%20to%20create%20index,the%20index%20must%20be%20distinct。 确保按照你查询的行添加组合索引。
如果这样做没有改善你的查询时间,那么应该改进查询。
注意:
CONCAT-LEAST-GREATEST - 这是为了构造一个“friends_id”?也许你真正想要一个“conversation_id”?目前,两个用户永远不会有多个“conversation”,对吗?
如果确实需要,为conversation_id创建一个新列。(目前,GROUP BY是低效的。)下面的代码消除了对这样一个id的需求。
并且拥有这些“covering”和“composite”索引:
删除KEY(to_id),KEY(from_id),因为我的新索引可以处理这两个索引的所有其他任务。
我认为这具有相同的效果,但运行速度更快。
将它们组合起来:
(加上这两个索引)
更多
我曾经错误地认为UNION DISTINCT可以替代对conversation_id的需求。但事实并非如此。我立即看到了一些解决方案: