5

Nel mio log delle query lente sto vedendo query lente comeMySQL lento query che utilizza l'indice e non è lento quando l'eseguo attraverso il profiler

 
# Time: 121107 16:34:02 
# [email protected]: web_node[web_node] @ localhost [127.0.0.1] 
# Thread_id: 34436186 Schema: test_db Last_errno: 0 Killed: 0 
# Query_time: 1.413751 Lock_time: 0.000222 Rows_sent: 203 Rows_examined: 203 Rows_affected: 0 Rows_read: 203 
# Bytes_sent: 7553 Tmp_tables: 0 Tmp_disk_tables: 0 Tmp_table_sizes: 0 
# InnoDB_trx_id: 9B04384 
SET timestamp=1352334842; 
SELECT id, email FROM test_data WHERE id IN (13089576,3002681,3117763,1622233,2941590,12305279,1732672,2446772,3189510,13084725,4943929,5855071,6572137,2266261,3003496,2024860,3336832,13758671,6477694,1796684,13001771,4690025,1071744,1017876,5175795,795988,1619821,2481819,2941090,4770802,13438250,3254708,2323402,526303,13219855,3313573,3190479,1733761,3300577,2941758,6474118,1733379,11523598,4205064,6521805,2492903,1860388,3337093,5205317,1213970,5442738,12194039,1214203,12970536,3076611,3126152,3677156,5305021,2751587,4954875,875480,2105172,5309382,12981920,5204330,13729768,3254503,5030441,2680750,590661,1338572,7272410,1860386,2567550,5434143,1918035,5329411,1683235,3254119,5175784,1855380,3336834,2102567,4749746,37269,3207031,6464336,2227907,2713471,3937600,2940442,2233821,5619141,5204711,5988803,5050821,10109926,5226877,5050275,1874115,13677832,5338699,2423773,6432937,6443660,1990611,6090667,6527411,6568731,3254846,3414049,2011907,5180984,12178711,8558260,3130655,5864745,2059318,3480233,2104948,2387703,1939395,5356002,2681209,1184622,1184456,10390165,510854,7983305,795991,2622393,4490187,9436477,5356051,2423464,5205318,1600499,13623229,3255205,12200483,6477706,3445661,5226284,1176639,13760962,2101681,6022818,12909371,1732457,2377496,7260091,12191702,2492899,2630691,13047691,1684470,9382108,2233737,13117701,1796698,2535914,4941741,4565958,1100410,2321180,13080467,813342,4563877,4689365,2104756,1102802,2714488,3188947,1599770,1558291,5592740,5233428,5204830,1574452,3188956,13693326,2102349,3704111,1748303,790889,9323280,4741494,2387900,5338213,3583795,2283942,3189482,3002296,4490123,3585020,962926,3481423,1600920,1682364,4693123,6487778,2677582,2377195);

Quando eseguo la query lento attraverso il profiler utilizzando SQL_NO_CACHE sembra dice

 
203 rows in set (0.03 sec) 

show profile for query 33; 
+----------------------+----------+ 
| Status    | Duration | 
+----------------------+----------+ 
| starting    | 0.000187 | 
| checking permissions | 0.000012 | 
| Opening tables  | 0.000034 | 
| System lock   | 0.000016 | 
| init     | 0.000087 | 
| optimizing   | 0.000024 | 
| statistics   | 0.028694 | 
| preparing   | 0.000074 | 
| executing   | 0.000005 | 
| Sending data   | 0.001596 | 
| end     | 0.000009 | 
| query end   | 0.000008 | 
| closing tables  | 0.000014 | 
| freeing items  | 0.001600 | 
| logging slow query | 0.000007 | 
| cleaning up   | 0.000011 | 
+----------------------+----------+ 

quando ho eseguito la query con spiegare che dice

 
+----+-------------+------------------+-------+------------------+----------+---------+------+------+--------------------------+ 
| id | select_type | table   | type | possible_keys | key  | key_len | ref | rows | Extra     | 
+----+-------------+------------------+-------+------------------+----------+---------+------+------+--------------------------+ 
| 1 | SIMPLE  | test_data  | range | PRIMARY,id_email | id_email | 4  | NULL | 203 | Using where; Using index | 
+----+-------------+------------------+-------+------------------+----------+---------+------+------+--------------------------+ 

la tabella di creare s come

 
CREATE TABLE `test_data` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `email` varchar(254) DEFAULT NULL, 
    `domain` varchar(254) DEFAULT NULL, 
    `age` smallint(6) DEFAULT NULL, 
    `gender` tinyint(1) DEFAULT NULL, 
    `location_id` int(11) unsigned DEFAULT NULL, 
    `created` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `unistall_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `subscription_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `active` tinyint(1) DEFAULT '1', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `email` (`email`), 
    KEY `domain` (`domain`), 
    KEY `id_email` (`id`,`email`), 
    KEY `email_id` (`email`,`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=13848530 DEFAULT CHARSET=utf8 

c'è un'altra domanda che viene eseguito regolarmente selezionando l'id e-mail da un elenco di indirizzi email da cui l'e-mail, tasto ID, l'indirizzo e-mail devono essere unici quindi, perché questa è una chiave univoca. Il tavolo ha solo ~ 14M righe

Ho pensato che forse gli indici sono diventati grandi per la memoria e lo scambio, ma la scatola ha 8 giga di RAM.

 
SELECT table_schema "Data Base Name", SUM(data_length + index_length)/1024/1024 "Data Base Size in MB", SUM(index_length)/1024/1024 "Index Size in MB" FROM information_schema.TABLES GROUP BY table_schema; 
+--------------------+----------------------+------------------+ 
| Data Base Name  | Data Base Size in MB | Index Size in MB | 
+--------------------+----------------------+------------------+ 
| metrics   |  3192.50000000 | 1594.42187500 | 
| data    |  8096.48437500 | 5639.51562500 | 
| raw_data   |  6000.35937500 |  745.07812500 | 
| information_schema |   0.00878906 |  0.00878906 | 
| mysql    |   0.04319191 |  0.04101563 | 
| performance_schema |   0.00000000 |  0.00000000 | 
+--------------------+----------------------+------------------+ 

Impostazione innodb_file_per_table = 1 nel file my.cnf sembra aver risolto il problema.

Questo ha migliorato il tempo di esecuzione, la mia comprensione è che avere il singolo file per tabella significa che l'ago del disco non ha bisogno di spostare distanze così grandi.

Domande

  1. Se la query può essere valutata utilizzando gli indici Perché l'impostazione innodb_file_per_table = 1 migliorare le prestazioni
  2. Perché è neanche il query lente quando viene eseguito per la profiler senza utilizzare la cache ?
  3. La mia chiave primaria dovrebbe essere (id, email)?

Aggiornamento

origine c'era alcun file /etc/my.cnf poi ho creato uno con il seguente

 
[mysqld] 
server-id=1 
max_connections=1500 
key_buffer_size=50M 
query_cache_limit=16M 
query_cache_size=256M 
thread_cache=16 
table_open_cache=4096 
sort_buffer_size=512K 
join_buffer_size=8M 
read_buffer_size=8M 
skip_name_resolve=1 
thread_cache_size=256 
innodb_buffer_pool_size=6G 
innodb_buffer_pool_instances=1 
innodb_thread_concurrency=96 
innodb_additional_mem_pool_size=32M 
innodb_log_buffer_size=8M 
innodb_flush_log_at_trx_commit=0 
innodb_log_file_size=256M 
innodb_flush_method=O_DIRECT 
innodb_file_per_table=1 
net_read_timeout=15 
net_write_timeout=30 
log-bin=mysql-bin 
sync_binlog=0 
datadir=/var/lib/mysql 

risposta

3

Hai troppi dati per la vostra innodb_log_buffer.

Quali sono i valori di:

innodb_buffer_pool_size 
innodb_log_file_size 

Tutti InnoDB deve essere eseguito in memoria. Quando si suddividono i file, viene eseguito in modo più efficiente poiché si scambia e si esaurisce la memoria con meno letture e scritture del disco quando un file di dimensioni maggiori impiega più tempo a eseguire la scansione dei dati.

Non si scambia perché il tuo innodb_buffer_pool_size limita la quantità di memoria che MySQL carica in memoria.

L'unico modo per risolvere il problema è ottenere più memoria e allocare abbastanza innodb_buffer_pool_size per tutte le tabelle e gli indici innodb.

+0

grazie per la spiegazione ho aggiornato la domanda originale con la risposta alla tua domanda. – Ben

+1

Sì - innodb_buffer_pool_size = 6G - i tuoi dati non rientrano in questo. Hai 16,8 GB di dati + indice. Se è possibile aumentare la memoria, questa è la soluzione migliore, altrimenti, prenderei in considerazione la possibilità di spostare alcuni dati in una tabella ARCHIVIO. – Michael