У меня есть следующий запрос:
SELECT
analytics.source AS referrer,
COUNT(analytics.id) AS frequency,
SUM(IF(transactions.status = 'COMPLETED', 1, 0)) AS sales
FROM analytics
LEFT JOIN transactions ON analytics.id = transactions.analytics
WHERE analytics.user_id = 52094
GROUP BY analytics.source
ORDER BY frequency DESC
LIMIT 10
Таблица аналитики имеет 60M строк, а таблица транзакций имеет 3M строки.
Когда я запускаю EXPLAIN
по этому запросу, я получаю:
+------+--------------+-----------------+--------+---------------------+-------------------+----------------------+---------------------------+----------+-----------+-------------------------------------------------+
| # id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | |
+------+--------------+-----------------+--------+---------------------+-------------------+----------------------+---------------------------+----------+-----------+-------------------------------------------------+
| '1' | 'SIMPLE' | 'analytics' | 'ref' | 'analytics_user_id | analytics_source' | 'analytics_user_id' | '5' | 'const' | '337662' | 'Using where; Using temporary; Using filesort' |
| '1' | 'SIMPLE' | 'transactions' | 'ref' | 'tran_analytics' | 'tran_analytics' | '5' | 'dijishop2.analytics.id' | '1' | NULL | |
+------+--------------+-----------------+--------+---------------------+-------------------+----------------------+---------------------------+----------+-----------+-------------------------------------------------+
Я не могу понять, как оптимизировать этот запрос, поскольку он уже очень простой. Для выполнения этого запроса требуется около 70 секунд.
Вот те индексы, которые существуют:
+-------------+-------------+----------------------------+---------------+------------------+------------+--------------+-----------+---------+--------+-------------+----------+----------------+
| # Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------------+-------------+----------------------------+---------------+------------------+------------+--------------+-----------+---------+--------+-------------+----------+----------------+
| 'analytics' | '0' | 'PRIMARY' | '1' | 'id' | 'A' | '56934235' | NULL | NULL | '' | 'BTREE' | '' | '' |
| 'analytics' | '1' | 'analytics_user_id' | '1' | 'user_id' | 'A' | '130583' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
| 'analytics' | '1' | 'analytics_product_id' | '1' | 'product_id' | 'A' | '490812' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
| 'analytics' | '1' | 'analytics_affil_user_id' | '1' | 'affil_user_id' | 'A' | '55222' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
| 'analytics' | '1' | 'analytics_source' | '1' | 'source' | 'A' | '24604' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
| 'analytics' | '1' | 'analytics_country_name' | '1' | 'country_name' | 'A' | '39510' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
| 'analytics' | '1' | 'analytics_gordon' | '1' | 'id' | 'A' | '56934235' | NULL | NULL | '' | 'BTREE' | '' | '' |
| 'analytics' | '1' | 'analytics_gordon' | '2' | 'user_id' | 'A' | '56934235' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
| 'analytics' | '1' | 'analytics_gordon' | '3' | 'source' | 'A' | '56934235' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
+-------------+-------------+----------------------------+---------------+------------------+------------+--------------+-----------+---------+--------+-------------+----------+----------------+
+----------------+-------------+-------------------+---------------+-------------------+------------+--------------+-----------+---------+--------+-------------+----------+----------------+
| # Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------------+-------------+-------------------+---------------+-------------------+------------+--------------+-----------+---------+--------+-------------+----------+----------------+
| 'transactions' | '0' | 'PRIMARY' | '1' | 'id' | 'A' | '2436151' | NULL | NULL | '' | 'BTREE' | '' | '' |
| 'transactions' | '1' | 'tran_user_id' | '1' | 'user_id' | 'A' | '56654' | NULL | NULL | '' | 'BTREE' | '' | '' |
| 'transactions' | '1' | 'transaction_id' | '1' | 'transaction_id' | 'A' | '2436151' | '191' | NULL | 'YES' | 'BTREE' | '' | '' |
| 'transactions' | '1' | 'tran_analytics' | '1' | 'analytics' | 'A' | '2436151' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
| 'transactions' | '1' | 'tran_status' | '1' | 'status' | 'A' | '22' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
| 'transactions' | '1' | 'gordon_trans' | '1' | 'status' | 'A' | '22' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
| 'transactions' | '1' | 'gordon_trans' | '2' | 'analytics' | 'A' | '2436151' | NULL | NULL | 'YES' | 'BTREE' | '' | '' |
+----------------+-------------+-------------------+---------------+-------------------+------------+--------------+-----------+---------+--------+-------------+----------+----------------+
Упрощенная схема для двух таблиц, прежде чем добавлять какие-либо дополнительные индексы, как было предложено, поскольку это не улучшило ситуацию.
CREATE TABLE 'analytics' (
'id' int(11) NOT NULL AUTO_INCREMENT,
'user_id' int(11) DEFAULT NULL,
'affil_user_id' int(11) DEFAULT NULL,
'product_id' int(11) DEFAULT NULL,
'medium' varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'source' varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'terms' varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'is_browser' tinyint(1) DEFAULT NULL,
'is_mobile' tinyint(1) DEFAULT NULL,
'is_robot' tinyint(1) DEFAULT NULL,
'browser' varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'mobile' varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'robot' varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'platform' varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'referrer' varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'domain' varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'ip' varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'continent_code' varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'country_name' varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'city' varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'date' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ('id'),
KEY 'analytics_user_id' ('user_id'),
KEY 'analytics_product_id' ('product_id'),
KEY 'analytics_affil_user_id' ('affil_user_id')
) ENGINE=InnoDB AUTO_INCREMENT=64821325 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE 'transactions' (
'id' int(11) NOT NULL AUTO_INCREMENT,
'transaction_id' varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'user_id' int(11) NOT NULL,
'pay_key' varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'sender_email' varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'amount' decimal(10,2) DEFAULT NULL,
'currency' varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'status' varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'analytics' int(11) DEFAULT NULL,
'ip_address' varchar(46) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'session_id' varchar(60) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
'date' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
'eu_vat_applied' int(1) DEFAULT '0',
PRIMARY KEY ('id'),
KEY 'tran_user_id' ('user_id'),
KEY 'transaction_id' ('transaction_id'(191)),
KEY 'tran_analytics' ('analytics'),
KEY 'tran_status' ('status')
) ENGINE=InnoDB AUTO_INCREMENT=10019356 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Если вышеизложенное не может быть оптимизировано дальше. Любая рекомендация по внедрению сводных таблиц будет отличной. Мы используем стек LAMP на AWS. Вышеуказанный запрос выполняется в RDS (m1.large).