web-dev-qa-db-fra.com

La jointure MySQL a des performances considérablement inférieures après la mise à niveau de 5.6 vers 5.7

J'ai une requête assez simple qui est devenue très lente après la mise à niveau de MySQL 5.6.35 vers MySQL 5.7.12 (fonctionnant sur AWS RDS).

SELECT DISTINCT 
  Name,d.id,deviceType,issuedBy, description,avNum,CompanyName,
  BrandName,dwNumber,quant,discDate,Type
FROM table_one d     
JOIN table_two i ON d.id = i.id;

En 5.6, cette requête se termine en 90 secondes. Après la mise à niveau vers 5.7, cela prend plus de 30 minutes. Chaque table comprend environ 2 millions de lignes.

J'ai commencé par comparer les paramètres d'optimisation entre 5.6 et 5.7:

# 5.6
index_merge=on
index_merge_union=on
index_merge_sort_union=on
index_merge_intersection=on
engine_condition_pushdown=on
index_condition_pushdown=on
mrr=on
mrr_cost_based=on
block_nested_loop=on
batched_key_access=off
materialization=on
semijoin=on
loosescan=on
firstmatch=on
subquery_materialization_cost_based=on
use_index_extensions=on
# 5.7
Optimizer settings in 5.7:
index_merge=on
index_merge_union=on
index_merge_sort_union=on
index_merge_intersection=on
engine_condition_pushdown=on
index_condition_pushdown=on
mrr=on
mrr_cost_based=on
block_nested_loop=on
batched_key_access=off
materialization=on
semijoin=on
loosescan=on
firstmatch=on
subquery_materialization_cost_based=on
use_index_extensions=on
condition_fanout_filter=on
derived_merge=on
duplicateweedout=on

Les seuls changements que je constate sont les trois dernières options de 5.7. Je les ai éteints comme suit:

SET optimizer_switch='condition_fanout_filter=off';
SET optimizer_switch='derived_merge=off';
SET optimizer_switch='duplicateweedout=off';

Cela n'a eu aucun effet. Ensuite, j'ai regardé les différences dans mes paramètres innodb (mon instance 5.7 a plus de mémoire, d'où les différences de taille de pool).

# my innodb changes 5.6 -> 5.7
innodb_adaptive_hash_index_parts added in 5.7, set to ‘8’
innodb_additional_mem_pool_size set to 8388608 in 5.6, removed in 5.7
innodb_buffer_pool_dump_at_shutdown changed from ‘OFF’ to ‘ON’
innodb_buffer_pool_dump_pct added in 5.7, set to ’25’
innodb_buffer_pool_load_at_startup changed from ‘OFF’ to ‘ON’
innodb_buffer_pool_size changed from 2,804,940,800 to 11,811,160,064
innodb_checksum_algorithm changed from ‘innodb’ to ‘crc32’
innodb_deadlock_detect added in 5.7, set to ‘ON’
innodb_default_row_format added in 5.7, set to ‘dynamic’
innodb_file_format changed from ‘Antelope’ to ‘Barracuda’
innodb_file_format_max changed from ‘Antelope’ to ‘Barracuda’
innodb_fill_factor added in 5.7 set to ‘100’
innodb_flush_sync added in 5.7 set to ‘ON’
innodb_log_checksums added in 5.7 set to ‘ON’
innodb_log_write_ahead_size added in 5.7 set to 8192
innodb_max_undo_log_size added in 5.7 set to 1,073,741,824
innodb_mirrored_log_groups removed in 5.7, set to ‘1’ in 5.6
innodb_numa_interleave added in 5.7 set to ‘OFF’
innodb_page_cleaners added in 5.7 set to ‘4’
innodb_purge_rseg_truncate_frequency added in 5.7 set to ‘128’
innodb_strict_mode changed from ‘OFF’ to ‘ON’
innodb_temp_data_file_path added in 5.7, set to 'ibtmp1:12M:autoextend'
innodb_undo_log_truncate added in 5.7, set to ‘OFF’

J'ai examiné le manuel de référence et tenté de désactiver les éléments suivants:

innodb_strict_mode=‘OFF’
innodb_deadlock_detect=‘OFF’
innodb_flush_sync=‘OFF’
innodb_log_checksums=‘OFF’

De plus, aucun effet.

J'espère que quelqu'un pourra me dire ce qui se passe ici? La requête fait partie d'un flux de travail plus vaste, qui est devenu inutilisable en conséquence. J'aimerais récupérer le comportement 5.6 si possible, mais avec mes connaissances DBA limitées, je suis à court de choses à essayer. J'espère que quelqu'un pourra m'orienter dans la bonne direction ou me donner des avenues supplémentaires pour enquêter.

Voici mes tableaux. Beaucoup de colonnes ont de grandes largeurs, et elles sont principalement définies comme VARCHAR(X) DEFAULT NULL parce que la source de données n'est pas propre (je n'ai pas de contrôle sur la source). Notez que j'ai besoin de données utf8, mais j'utilise latin1 pendant que je dépanne la requête lente, pour éliminer cela comme une cause possible de la lenteur. (La raison pour laquelle nous devons migrer de 5.6 à> 5.7 est pour les tailles d'index plus grandes dans 5.7, qui peuvent accueillir nos tailles de colonnes UTF8 plus grandes).

(De plus, je dois souligner que le champ id provient des données source et est une longue chaîne de caractères alphanumériques de largeur variable (jusqu'à ~ 30 caractères), donc j'ai besoin que ce soit un VARCHAR ).

CREATE TABLE `table_one` (
  `id` varchar(200) NOT NULL DEFAULT '',
  `RecordKey` varchar(50) DEFAULT NULL,
  `VersionStat` varchar(200) DEFAULT NULL,
  `Status` varchar(200) DEFAULT NULL,
  `VersionNumber` varchar(50) DEFAULT NULL,
  `VersionDate` varchar(20) DEFAULT NULL,
  `PublishDate` varchar(20) DEFAULT NULL,
  `DistStart` varchar(20) DEFAULT NULL,
  `DistCommStat` varchar(2000) DEFAULT NULL,
  `BrandName` varchar(100) DEFAULT NULL,
  `VersionModelNumber` varchar(100) DEFAULT NULL,
  `Catalog` varchar(100) DEFAULT NULL,
  `dwNumber` varchar(100) DEFAULT NULL,
  `CompanyName` varchar(500) DEFAULT NULL,
  `DeviceCount` varchar(200) DEFAULT NULL,
  `description` varchar(3000) DEFAULT NULL,
  `Exemption` varchar(1100) DEFAULT NULL,
  `PreMarket` varchar(1500) DEFAULT NULL,
  `DevDRMT` varchar(1000) DEFAULT NULL,
  `DTKit` varchar(200) DEFAULT NULL,
  `Combination` varchar(250) DEFAULT NULL,
  `Usage` varchar(500) DEFAULT NULL,
  `SingleBatch` varchar(50) DEFAULT NULL,
  `SerialNumber` varchar(250) DEFAULT NULL,
  `ManuDate` varchar(20) DEFAULT NULL,
  `ExpDate` varchar(20) DEFAULT NULL,
  `Donation` varchar(50) DEFAULT NULL,
  `LabeldWithMLO` varchar(50) DEFAULT NULL,
  `NLabledMLO` varchar(50) DEFAULT NULL,
  `MLOStatus` varchar(1000) DEFAULT NULL,
  `BTT` varchar(50) DEFAULT NULL,
  `OPP` varchar(50) DEFAULT NULL,
  `BRC` varchar(50) DEFAULT NULL,
  `PriorUse` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `table_two` (
  `id` varchar(200) DEFAULT NULL,
  `Name` varchar(200) DEFAULT NULL,
  `deviceType` varchar(50) DEFAULT NULL,
  `issuedBy` varchar(200) DEFAULT NULL,
  `avNum` varchar(50) DEFAULT NULL,
  `quant` varchar(50) DEFAULT NULL,
  `discDate` varchar(50) DEFAULT NULL,
  `PkgStatus` varchar(50) DEFAULT NULL,
  `Type` varchar(50) DEFAULT NULL,
  KEY `idx_table_two_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

EXPLAIN est également identique entre les deux:

explain extended SELECT DISTINCT ...

******************** 1. row *********************
           id: 1
  select_type: SIMPLE
        table: d
         type: ALL
possible_keys: PRIMARY
          key: 
      key_len: 
          ref: 
         rows: 1596593
     filtered: 100.00
        Extra: Using temporary
******************** 2. row *********************
           id: 1
  select_type: SIMPLE
        table: i
         type: ref
possible_keys: idx_table_two_id
          key: idx_table_two_id
      key_len: 203
          ref: mydb.d.id
         rows: 1
     filtered: 100.00
        Extra: 

MISE À JOUR # 1:

Voici quelques informations supplémentaires. J'ai activé le schéma de performances sur les deux serveurs. Le serveur 5.7 affiche de nombreux hash_table_locks:

SELECT EVENT_NAME, COUNT_STAR
       FROM performance_schema.events_waits_summary_global_by_event_name
       ORDER BY COUNT_STAR DESC LIMIT 10;


# EVENT_NAME, COUNT_STAR
'wait/synch/sxlock/innodb/hash_table_locks',   '3256808433'
'wait/synch/mutex/innodb/buf_pool_mutex',      '19266748'
'wait/synch/mutex/innodb/log_sys_mutex',       '14488781'
'wait/io/table/sql/handler',                   '13676918'
'wait/synch/mutex/innodb/lock_mutex',          '11431841'
...

De plus, je vois beaucoup de temps passé dans wait/io/table/sql/handler, Probablement à cause de hash_table_locks. Ils sont les deux premiers consommateurs de temps (en picosecondes):

SELECT EVENT_NAME, SUM_TIMER_WAIT
       FROM performance_schema.events_waits_summary_global_by_event_name where event_name != "idle"
       ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;

# EVENT_NAME, SUM_TIMER_WAIT
'wait/io/table/sql/handler',                 '1300909619487480' # 1300s
'wait/synch/sxlock/innodb/hash_table_locks', '98099101074540'   # 98s
'wait/io/file/innodb/innodb_data_file',      '5035505718525'
'wait/io/socket/sql/client_connection',      '344937541275'
'wait/synch/mutex/innodb/fil_system_mutex',  '198749837865'
...

Quand je répète cela sur le serveur 5.6, je ne vois pas le temps hash_table_locks Comme celui-ci.

MISE À JOUR # 2:

Pour vérifier si le disque est le goulot d'étranglement, j'ai fait ce qui suit.

J'ai installé deux instances EC2 identiques. Ils sont tous deux i3.large (2 vCPU/15,25 Go de RAM) avec un disque SSD 1x425 Go. Sur la première instance, j'ai installé MySQL 5.7.25. Sur la deuxième instance, j'ai installé MariaDB 10.2.21. J'ai gardé la configuration prête à l'emploi pour les deux. La requête sur MySQL prend toujours 30 minutes, mais l'instance MariaDB ne prend que 30 secondes! Les versions d'InnoDB sont presque identiques: MySQL exécute 5.7.25 et MariaDB exécute 5.7.24. Il me semble que cela doit être un problème de configuration au sein de MySQL, plutôt qu'une limitation d'Innodb ou du disque.

Autre mise à jour: au sein de l'instance MariaDB, EXPLAIN est légèrement différent. Il existe une clause "using where" et les tableaux sont inversés. J'ai tenté un STRAIGHT_JOIN pour modifier l'ordre des tables, mais cela n'a rien changé:

# MariaDB
EXPLAIN SELECT SQL_NO_CACHE DISTINCT
  Name,d.id,deviceType,issuedBy, description,avNum,CompanyName,
  BrandName,dwNumber,quant,discDate,Type
FROM table_one d    
JOIN table_two i ON d.id = i.id;


******************** 1. row *********************
           id: 1
  select_type: SIMPLE
        table: i
         type: ALL
possible_keys: idx_table_two_id
          key:
      key_len:
          ref:
         rows: 2496908
        Extra: Using where; Using temporary
******************** 2. row *********************
           id: 1
  select_type: SIMPLE
        table: d
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 202
          ref: mydb.i.id
         rows: 1
        Extra:
2 rows in set

J'ai également appliqué les modifications suggérées par Wilson ci-dessous, qui n'ont pas résolu le problème.

MISE À JOUR # 3:

J'ai trouvé quelque chose qui semble important. J'ai activé le traceur de requêtes sur mes serveurs 5.6 et 5.7. J'ai joint leur sortie ici:

5.6: https://Pastebin.com/KSTeTDdy

5.7: https://Pastebin.com/3SaXNdC

À la toute fin, j'ai remarqué que les tables temporaires sont créées différemment:

# 5.6
{
  "converting_tmp_table_to_myisam": {
    "cause": "memory_table_size_exceeded",
    "tmp_table_info": {
      "table": "intermediate_tmp_table",
      "row_length": 4570,
      "key_length": 4585,
      "unique_constraint": true,
      "location": "disk (MyISAM)",
      "record_format": "packed"
    }
  }
}
# 5.7
{
  "converting_tmp_table_to_ondisk": {
    "cause": "memory_table_size_exceeded",
    "tmp_table_info": {
      "table": "intermediate_tmp_table",
      "row_length": 4575,
      "key_length": 8,
      "unique_constraint": true,
      "location": "disk (InnoDB)",
      "record_format": "packed"
    }
  }
}

5.6 utilise MyISAM pour la table tmp et 5.7 utilise InnoDB. C'est peut-être pourquoi je vois autant d'occurrences de wait/synch/sxlock/innodb/hash_table_locks En 5.7? Cela pourrait-il être lié au verrouillage de niveau de ligne InnoDB? La question est, est-il possible de restaurer l'ancien comportement à tester?

J'ai trouvé internal_tmp_disk_storage_engine Et l'ai changé en MyISAM sur le serveur 5.7. Cela ne résout pas non plus le problème. Je peux voir la table temporaire en cours de création sous/tmp:

# ls -ltrh /tmp
-rw-rw---- 1 mysql mysql  56K Apr 26 02:27 #sql_f55_0.MAI
-rw-rw---- 1 mysql mysql 368M Apr 26 02:27 #sql_f55_0.MAD

Il utilise définitivement MyISAM maintenant, mais la requête est toujours lente. Je remarque que sur tous les serveurs, 5.7, 5.6 et MariaDB, cette taille de fichier passe à 368 Mo, puis cesse de s'agrandir. Le fichier croît BEAUCOUP plus rapidement en 5.6/MariaDB (~ 10-15 Mo/s) par rapport à 5.7 (<1 Mo/s).

4
blindsnowmobile

Analyse des VARIABLES et du STATUT MONDIAL:
(Hélas, rien ici ne ressort comme une explication de la question en main)

Je n'aime pas faire FORCE INDEX, etc., mais STRAIGHT_JOIN peut être le moyen le plus simple et le plus sûr de forcer le classement des deux tables.

Observations:

  • Version: 5.7.25-log
  • 15,25 Go de RAM
  • Uptime = 14:05:48; certaines valeurs GLOBAL STATUS peuvent ne pas encore être significatives.
  • Vous n'êtes pas en cours d'exécution sur Windows.
  • Exécution de la version 64 bits
  • Vous semblez exécuter entièrement (ou principalement) InnoDB.

Les problèmes les plus importants:

Avec SSD, changez-les:

innodb_flush_neighbors = 0 - à partir de 1 innodb_io_capacity = 800 - à partir de 200

Il semble que la taille de votre jeu de données soit considérablement inférieure à innodb_buffer_pool_size. Donc, vous payez peut-être plus RAM que ce dont vous avez besoin? Si vous vous préparez à la croissance, ignorez ce commentaire.

À de rares exceptions près, je ne pense pas que innodb_deadlock_detect doit être désactivé.

Beaucoup de requêtes mal exécutées. Réduisez le long_query_time et utilisez le slowlog: http://mysql.rjweb.org/doc.php/mysql_analysis#slow_queries_and_slowlog

Étant donné que seules 11 connexions semblent nécessaires, une baisse de max_connections à, disons 40. Cela évitera certaines pressions sur la RAM.

Es-tu sûr que tu veux READ-UNCOMMITTED?

Détails et autres observations:

( Table_open_cache_misses / (Table_open_cache_hits + Table_open_cache_misses) ) = 272 / (6879 + 272) = 3.8% - Efficacité de table_open_cache. - Augmentez table_open_cache et vérifiez table_open_cache_instances.

( innodb_lru_scan_depth * innodb_page_cleaners ) = 1,024 * 4 = 4,096 - Quantité de travail pour les nettoyeurs de pages chaque seconde. - "InnoDB: page_cleaner: la boucle prévue de 1000 ms a pris ..." peut être corrigée en réduisant lru_scan_depth: Considérez 1000/innodb_page_cleaners

( innodb_page_cleaners / innodb_buffer_pool_instances ) = 4 / 8 = 0.5 - innodb_page_cleaners - Recommande de définir innodb_page_cleaners sur innodb_buffer_pool_instances

( innodb_lru_scan_depth ) = 1,024 - "InnoDB: page_cleaner: la boucle prévue de 1000 ms a pris ..." peut être corrigé en baissant lru_scan_depth

( Innodb_buffer_pool_pages_free / Innodb_buffer_pool_pages_total ) = 494,639 / 720896 = 68.6% - Le PCT de buffer_pool n'est pas utilisé actuellement - innodb_buffer_pool_size est plus grand que nécessaire?

( Innodb_buffer_pool_bytes_data / innodb_buffer_pool_size ) = 3,590,832,128 / 11264M = 30.4% - Pourcentage du pool de mémoire tampon occupé par les données - Un petit pourcentage peut-être indique que le pool de mémoire tampon est inutilement grand.

( Uptime / 60 * innodb_log_file_size / Innodb_os_log_written ) = 50,748 / 60 * 128M / 2513408 = 45,166 - Minutes entre les rotations du journal InnoDB À partir de 5.6.8, cela peut être modifié dynamiquement; assurez-vous également de modifier my.cnf. - (La recommandation de 60 minutes entre les rotations est quelque peu arbitraire.) Ajustez innodb_log_file_size. (Ne peut pas changer dans AWS.)

( innodb_flush_neighbors ) = 1 - Une optimisation mineure lors de l'écriture de blocs sur le disque. - Utilisez 0 pour les disques SSD; 1 pour le disque dur.

( innodb_io_capacity ) = 200 - Opérations d'E/S par seconde capables sur le disque. 100 pour les lecteurs lents; 200 pour les entraînements en rotation; 1000-2000 pour les SSD; multiplier par le facteur RAID.

( innodb_thread_concurrency ) = 0 - 0 = Laissez InnoDB décider du meilleur pour concurrency_tickets. - Réglez sur 0 ou 64. Cela peut réduire le processeur.

( innodb_print_all_deadlocks ) = innodb_print_all_deadlocks = OFF - Indique s'il faut enregistrer tous les blocages. - Si vous êtes en proie à des blocages, activez-le. Attention: Si vous avez beaucoup de blocages, cela peut écrire beaucoup sur le disque.

( innodb_deadlock_detect ) = innodb_deadlock_detect = OFF - 5.7.15 permet d'accélérer l'insertion lourde en désactivant la détection de blocage - Voulez-vous vraiment la désactiver?

( local_infile ) = local_infile = ON - local_infile = ON est un problème de sécurité potentiel

( Created_tmp_disk_tables / Questions ) = 37,591 / 73621 = 51.1% - Nombre de requêtes nécessitant une table tmp sur disque. - De meilleurs index/aucun blobs/etc.

( Created_tmp_disk_tables / Created_tmp_tables ) = 37,591 / 46560 = 80.7% - Pourcentage de tables temporaires qui se sont répandues sur le disque - Peut-être augmenter tmp_table_size et max_heap_table_size; améliorer les index; éviter les taches, etc.

( (Com_insert + Com_update + Com_delete + Com_replace) / Com_commit ) = (168 + 0 + 2 + 0) / 170 = 1 - Déclarations par engagement (en supposant que tous les InnoDB) - Faible: Peut aider à regrouper les requêtes dans les transactions; Élevé: les transactions longues mettent à rude épreuve diverses choses.

( Select_scan ) = 51,492 / 50748 = 1 /sec - analyses complètes des tables - Ajouter des index/optimiser les requêtes (sauf s'il s'agit de petites tables)

( Select_scan / Com_select ) = 51,492 / 71543 = 72.0% -% de sélections effectuant une analyse complète de la table. (Peut être trompé par les routines stockées.) - Ajouter des index/optimiser les requêtes

( ( Com_stmt_prepare - Com_stmt_close ) / ( Com_stmt_prepare + Com_stmt_close ) ) = ( 2 - 0 ) / ( 2 + 0 ) = 100.0% -- Es-tu ( binlog_format ) = binlog_format = MIXED - DÉCLARATION/RANGÉE/MIXTE. ROW est préféré; il peut devenir la valeur par défaut.

( expire_logs_days ) = 0 - Combien de temps pour purger automatiquement binlog (après ce nombre de jours) - Trop grand (ou zéro) = consomme de l'espace disque; trop petit = besoin de répondre rapidement à un crash réseau/machine.

( slow_query_log ) = slow_query_log = OFF - Indique s'il faut consigner les requêtes lentes. (5.1.12)

( long_query_time ) = 10 - Coupure (secondes) pour définir une requête "lente". - Suggérer 2

( Threads_created / Connections ) = 11 / 197 = 5.6% - Rapidité de la création du processus - Augmenter thread_cache_size (non Windows)

( thread_cache_size / max_connections ) = 21 / 1320 = 1.6% - (0 pour Windows)

( thread_cache_size / Max_used_connections ) = 21 / 11 = 190.9% - Il n'y a aucun avantage à avoir un cache de threads plus grand que votre nombre probable de connexions. Le gaspillage d'espace est l'inconvénient.

Vous avez la moitié du cache de requête. Vous devez définir à la fois query_cache_type = OFF et query_cache_size = 0. Il y a (selon une rumeur) un "bug" dans le code QC qui laisse du code à moins que vous ne désactiviez ces deux paramètres.

Anormalement petit:

Com_set_option = 6.7 /HR
Handler_read_rnd = 0.85 /HR
Innodb_dblwr_pages_written / Innodb_dblwr_writes = 1.05
Select_range = 0
Select_range / Com_select = 0
Sort_rows = 0.85 /HR
Table_locks_immediate = 0.03 /sec
Table_open_cache_hits = 0.14 /sec

Anormalement grand:

(Com_select + Qcache_hits) / (Com_insert + Com_update + Com_delete + Com_replace) = 420
Com_alter_user = 0.071 /HR
Com_flush = 12 /HR
Com_purge = 12 /HR
Com_release_savepoint = 0.071 /HR
Com_savepoint = 0.071 /HR
Handler_read_next / Handler_read_key = 145
Handler_read_rnd_next / Handler_read_rnd = 2.43e+6
Handler_savepoint = 0.071 /HR
Handler_savepoint_rollback = 0.28 /HR
Innodb_buffer_pool_pages_flushed / max(Questions, Queries) = 1.24
Performance_schema_file_instances_lost = 2

Chaînes anormales:

ft_boolean_syntax = + -><()~*:&
gtid_mode = OFF_PERMISSIVE
have_ssl = YES
innodb_fast_shutdown = 1
innodb_flush_sync = OFF
innodb_log_checksums = OFF
log_output = TABLE
log_statements_unsafe_for_binlog = OFF
optimizer_trace = enabled=off,one_line=off
optimizer_trace_features = greedy_search=on, range_optimizer=on, dynamic_range=on, repeated_subselect=on
relay_log_recovery = ON
session_track_system_variables = time_zone, autocommit, character_set_client, character_set_results, character_set_connection
time_zone = UTC
transaction_isolation = READ-UNCOMMITTED
tx_isolation = READ-UNCOMMITTED
2
Rick James

Vous avez augmenté RAM avec l'augmentation de la taille du pool de mémoire tampon innodb de ~ 2G à ~ 11G, ce qui représente ~ 70% du total RAM me semble correct.

Étant donné que le plan d'exécution et les configurations de base de données sont identiques, vous pouvez examiner votre configuration matérielle. Confirmez deux choses du côté matériel:

  1. Comparaison de la vitesse d'horloge du processeur entre la précédente et la actuelle
  2. Catégorie de disque précédente et actuelle (capacité d'écriture/lecture) de la machine et s'il y a une répartition de disque que vous utilisez.

Pour un côté plus sûr, voudriez-vous anlayze la table. Si la taille du tableau est plus petite, vous pouvez également l'optimiser pour supprimer toute fragmentation. Pour obtenir le rapport de fragmentation, vous pouvez exécuter l'outil mysqltuner sur votre base de données.

J'espère que cela t'aides.

Merci, Sanjeeva

1
thisissanjeeva.com

En analysant vos tables, ils utilisent tous deux des identifiants uniques pour l'ID de champ, de sorte que la clause distincte n'est pas nécessaire (et c'est cher), vous êtes donc libre de le supprimer.

Modifiez l'ordre de vos tables dans votre requête, en échangeant table_one et table_two comme suit:

SELECT Name,d.id,deviceType,issuedBy, description,avNum,CompanyName,   
BrandName,dwNumber,quant,discDate,Type
FROM table_two d 
JOIN table_one i 
ON d.id = i.id;

Une fois que vous faites cela, lorsque vous exécutez la requête d'explication, vous devriez voir dans la section supplémentaire ce qui suit: en utilisant où, et non plus en utilisant temporaire = (après avoir supprimé le distinct).

Dans ma boîte MySQL 5.6.43, j'obtiens ce résultat.

    explain SELECT d.Name,d.id,d.deviceType,d.issuedBy, i.description,d.avNum,i.CompanyName,    
i.BrandName,i.dwNumber,d.quant,d.discDate,d.Type
 FROM table_one i inner  JOIN table_two d 
ON d.id = i.id;
+----+-------------+-------+------+------------------+------------------+---------+----------+------+-------+
| id | select_type | table | type | possible_keys    | key              | key_len | ref      | rows | Extra |
+----+-------------+-------+------+------------------+------------------+---------+----------+------+-------+
|  1 | SIMPLE      | i     | ALL  | PRIMARY          | NULL             | NULL    | NULL     |    1 | NULL  |
|  1 | SIMPLE      | d     | ref  | idx_table_two_id | idx_table_two_id | 203     | upc.i.id |    1 | NULL  |
+----+-------------+-------+------+------------------+------------------+---------+----------+------+-------+



explain SELECT d.Name,d.id,d.deviceType,d.issuedBy, i.description,d.avNum,i.CompanyName,    i.BrandName,i.dwNumber,d.quant,d.discDate,d.Type 
FROM table_two d inner  JOIN table_one i 
ON d.id = i.id;

+----+-------------+-------+--------+------------------+---------+---------+----------+------+-------------+
| id | select_type | table | type   | possible_keys    | key     | key_len | ref      | rows | Extra       |
+----+-------------+-------+--------+------------------+---------+---------+----------+------+-------------+
|  1 | SIMPLE      | d     | ALL    | idx_table_two_id | NULL    | NULL    | NULL     |    1 | Using where |
|  1 | SIMPLE      | i     | eq_ref | PRIMARY          | PRIMARY | 202     | upc.d.id |    1 | NULL        |
+----+-------------+-------+--------+------------------+---------+---------+----------+------+-------------+

Veuillez exécuter les commandes d'explication telles que je les ai mises et dites-moi si vous obtenez le même résultat que moi.

Essayez également d'exécuter votre requête sans le distinct et voyez si vous obtenez un gain de performances significatif.

Le 21 avril 2019, ypercube a souligné l'absence de CLÉ PRIMAIRE et aucune spécification UNIQUE pour votre table_two. Tenez compte des éléments suivants, s'il vous plaît.

CREATE TABLE `table_two` (
`aincid` INT AUTO_INCREMENT PRIMARY KEY,
`id` varchar(200) NOT NULL DEFAULT 'idUNKNOWN',
`Name` varchar(200) DEFAULT NULL,
`deviceType` varchar(50) DEFAULT NULL,
`issuedBy` varchar(200) DEFAULT NULL,
`avNum` varchar(50) DEFAULT NULL,
`quant` varchar(50) DEFAULT NULL,
`discDate` varchar(50) DEFAULT NULL,
`PkgStatus` varchar(50) DEFAULT NULL,
`Type` varchar(50) DEFAULT NULL,
KEY `idx_table_two_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Ensuite, affichez les résultats EXPLAIN SELECT SQL_NO_CACHE ......, s'il vous plaît.

1
Wilson Hauck

Taux par seconde = Suggestions RPS pour votre section d'instance 5.7 [mysqld] à considérer,

innodb_lru_scan_depth=100  # from 1024 to conserve 90% of CPU cycles for the function
innodb_io_capacity=1900  # from 200 to allow higher IOPS on your SSD
innodb_flushing_avg_loops=5  # from 30 to reduce innodb_buffer_pool_pages_dirty of 26
read_buffer_size=512K  # from 256K to reduce handler_read_next RPS of 47,391
read_rnd_buffer_size=256K  # from 512K to reduce handler_read_rnd_next RPS of 574

Avertissement: je suis l'auteur du contenu du site Web mentionné dans mon profil, le profil réseau et des suggestions supplémentaires et des scripts utilitaires gratuits sont disponibles.

0
Wilson Hauck

Pouvez-vous savoir sur quel état la requête est bloquée à l'aide de la liste de processus ou à l'aide du profileur?

Essayez:

mysql> SET SESSION profiling = 1; 
mysql> <<EXECUTE YOUR QUERY >>;
mysql> SHOW PROFILES;
mysql> SHOW PROFILE FOR << Query Id >>;

Si votre requête reste dans l'état statistics, vous devez rechercher optimizer-search-depth=# paramètre.

J'espère que cela peut vous aider.

0
JYOTI RAJAI