La requête de la base de données MySQL prend un certain temps
P粉764836448
2023-08-31 22:29:19
<p>J'ai une grande base de données de messages avec 24 000 lignes :</p>
<pre class="brush:php;toolbar:false;">Afficher les lignes 0 à 24 (2 455 455 lignes au total, la requête prend 0,0006 seconde). ≪/pré>
<p>, je dois donc charger les conversations plus rapidement. Pour les utilisateurs ayant moins de conversations, le chargement est le suivant (l'utilisateur a 3,2 000 conversations) : </p>
<pre class="brush:php;toolbar:false;">Afficher les lignes 0 à 24 (3 266 lignes au total, la requête prend 0,0345 secondes) [id : 5009666... - 4375619...]. ≪/pré>
<p>Chargement plus lent pour les utilisateurs ayant de nombreuses conversations (l'utilisateur a 40 000 conversations) : </p>
<pre class="brush:php;toolbar:false;">Afficher les lignes 0 à 24 (40 296 lignes au total, la requête prend 5,1763 secondes) [id : 5021561... - 5015545...]. ≪/pré>
<p>J'utilise des clés d'index pour ces colonnes : </p>
<pre class="brush:php;toolbar:false;">id, to_id, from_id, heure, vu</pre>
<p>Table de base de données : </p>
<pre class="brush:php;toolbar:false;">CREATE TABLE `messages` (
`id` int(255) NON NULL,
`to_id` int(20) NON NULL,
`from_id` int(20) NON NULL,
`message` texte long NON NULL,
`time` double NON NULL,
`vu` int(2) NON NULL,
) MOTEUR=InnoDB CHARSET PAR DÉFAUT=latin1;
INSÉRER DANS `messages` (`id`, `to_id`, `from_id`, `message`, `time`, `seen`) VALEURS
(2, 6001, 2, 'Bonjour', 1587581995.5222, 1) ;
ALTER TABLE `messages`
AJOUTER UNE CLÉ PRIMAIRE (`id`),
AJOUTER UNE CLÉ `time_idx` (`time`),
AJOUTER LA CLÉ `from_idx` (`from_id`),
AJOUTER LA CLÉ `to_idx` (`to_id`),
AJOUTER UNE CLÉ `seenx` (`seen`),
AJOUTER UNE CLÉ `idx` (`id`);
ALTER TABLE `messages`
MODIFIER `id` int(255) NON NULL AUTO_INCREMENT, AUTO_INCREMENT=5021570 ;
COMMIT;</pré>
<p>J'utilise la requête suivante : </p>
<pre class="brush:php;toolbar:false;">SELECT
*
DEPUIS
messages,
(
SÉLECTIONNER
MAX(id) comme dernier identifiant
DEPUIS
messages
OÙ
(
messages.to_id = '1' -- l'ID à comparer (l'ID de l'utilisateur connecté)
OU messages.from_id = '1' -- l'ID à comparer (l'ID de l'utilisateur connecté)
)
PAR GROUPE
CONCAT(
LE MOINS (messages.to_id, messages.from_id),
'.',
GREATEST(messages.to_id, messages.from_id)
)
) comme conversations
OÙ
identifiant = conversations.lastid
COMMANDÉ PAR
messages.id DESC</pre>
<p>Je ne sais pas comment accélérer les choses pour les utilisateurs ayant beaucoup de conversations, si je dois recréer la structure de la base de données. </p>
Hmm, vous pourriez peut-être essayer d'ajouter des index à vos tables : https://www.drupal.org/docs/7/guidelines-for-sql/the-benefits-of-indexing-large-mysql-tables# : ~ :text=Création%20Indexes&text=Le%20statement%20to%20create%20index,le%20index%20must%20be%20distinct. Assurez-vous d'ajouter un index composite basé sur les lignes que vous interrogez.
Si cela n'améliore pas le temps de votre requête, alors la requête doit être améliorée.
Remarque :
CONCAT-LEAST-GREATEST - Est-ce pour construire un "friends_id" ? Peut-être que ce que vous voulez vraiment, c'est un « conversation_id » ? Actuellement, deux utilisateurs ne peuvent jamais avoir plusieurs « conversations », n’est-ce pas ?
Créez une nouvelle colonne pour conversation_id si vous en avez vraiment besoin. (Actuellement, GROUP BY est inefficace.) Le code suivant élimine le besoin d'un tel identifiant.
Et avoir ces index « couvrants » et « composites » :
Suppression de KEY(to_id), KEY(from_id) car mon nouvel index peut gérer toutes les autres tâches de ces deux index.
Je pense que cela a le même effet mais fonctionne plus vite.
Combinez-les :
(Ajoutez ces deux index)
Plus
J'ai pensé un jour à tort que UNION DISTINCT pourrait remplacer le besoin de conversation_id. mais ce n'est pas la vérité. J'ai tout de suite vu quelques solutions :