mysql - 优化选择分组依据

标签 mysql query-optimization

我有这个查询

SELECT 
    DC.variationID, COUNT(DISTINCT(DC.userID)) AS conversion
FROM 
    XXXX AS DC
WHERE 
    DC.testID = 'XXXX' AND DC.visit > 1
GROUP BY 
    DC.variationID

这是表格的描述

CREATE TABLE `XXXX` 
(
   `id` bigint(20) NOT NULL AUTO_INCREMENT,
   `userID` bigint(17) NOT NULL,
   `testID` bigint(20) NOT NULL,
   `variationID` bigint(20) NOT NULL,
   `url` bigint(20) NOT NULL,
   `time` bigint(20) NOT NULL,
   `visit` bigint(20) NOT NULL DEFAULT '1',
   `isTestPage` tinyint(1) NOT NULL,
   PRIMARY KEY (`id`,`testID`),
   KEY `url` (`url`),
   KEY `dc3_testIDPage` (`testID`,`url`),
   KEY `testid_istest` (`testID`,`isTestPage`),
   KEY `dc3_varIDPage` (`variationID`,`url`),
   KEY `index_rebond` (`testID`,`visit`,`variationID`),
   KEY `dc3_testIDvarIDPage` (`testID`,`variationID`,`url`),
   KEY `isTestPage2` (`variationID`,`isTestPage`,`visit`,`userID`),
   KEY `user_test_varID_url` (`userID`,`testID`,`variationID`,`url`)
 ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED

这是查询的解释

# id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
'1', 'SIMPLE', 'DC', NULL, 'ref', 'dc3_testIDPage,testid_istest,dc3_varIDPage,index_rebond,dc3_testIDvarIDPage,isTestPage2,user_test_varID_url', 'dc3_testIDvarIDPage', '8', 'const', '13695309', '33.33', 'Using index condition; Using where'

对我来说,查询应该使用索引“index_rebond”,但不幸的是它没有使用它。我很确定在查询之前使用索引“index_rebond”。

该查询需要很长时间才能完成。您能否告诉我为什么查询不使用索引“index_rebond”以及优化查询的最佳方法是什么?

这是显示索引的结果

# Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment
'datacollect_v3', '0', 'PRIMARY', '1', 'id', 'A', '25909280', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '0', 'PRIMARY', '2', 'testID', 'A', '25909280', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'url', '1', 'url', 'A', '1657369', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'dc3_testIDPage', '1', 'testID', 'A', '2167', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'dc3_testIDPage', '2', 'url', 'A', '1850256', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'testid_istest', '1', 'testID', 'A', '3813', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'testid_istest', '2', 'isTestPage', 'A', '5721', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'dc3_varIDPage', '1', 'variationID', 'A', '2053', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'dc3_varIDPage', '2', 'url', 'A', '4171834', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'index_rebond', '1', 'testID', 'A', '1811', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'index_rebond', '2', 'visit', 'A', '11357', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'index_rebond', '3', 'variationID', 'A', '17208', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'dc3_testIDvarIDPage', '1', 'testID', 'A', '2049', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'dc3_testIDvarIDPage', '2', 'variationID', 'A', '3513', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'dc3_testIDvarIDPage', '3', 'url', 'A', '929052', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'isTestPage2', '1', 'variationID', 'A', '1891', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'isTestPage2', '2', 'isTestPage', 'A', '3309', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'isTestPage2', '3', 'visit', 'A', '16172', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'isTestPage2', '4', 'userID', 'A', '2712038', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'user_test_varID_url', '1', 'userID', 'A', '1103566', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'user_test_varID_url', '2', 'testID', 'A', '1336479', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'user_test_varID_url', '3', 'variationID', 'A', '1325388', NULL, NULL, '', 'BTREE', '', ''
'datacollect_v3', '1', 'user_test_varID_url', '4', 'url', 'A', '16936138', NULL, NULL, '', 'BTREE', '', ''

最诚挚的问候,

最佳答案

PRIMARY KEY (id, testID) 没有意义,除非您按 testID 进行分区。你不应该有主键(id)吗?

如果您有一些自然唯一的列组合,请考虑删除 id 并使用该组合作为 PK。

这将是“覆盖”,因此可能会更快:

INDEX(testID, visit, variationID, userID)

(并去掉index_rebond,因为它是多余的。)isTestPage2也被覆盖(因为包含PK),但它的排序效率低下。

除非您确实希望拥有超过 40 亿个各种 ID,否则建议您将它们切换为 INT UNSIGNED(此处和其他表中)。将此表及其索引减半将有助于提高性能,尤其是在数据集太大而无法缓存的情况下。

关于mysql - 优化选择分组依据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39512806/

相关文章:

php - 记录用户操作和页面浏览量的最有效方式是什么?

php - MySql 使用 ip 创建或更新行?

sql - 在 SQL 中查找包含相同数字序列的字符串的最佳方法是什么? (假手机搜索)

php - 将值计算从 SQL 移到 PHP 层是否更好?

mysql - 为什么我的查询会返回很多结果?

mysql - 将 XAMPP 文件夹移动到新计算机,现在在尝试启动 MySQL 时得到 "(XAMPPErrorDomain error 1.)"

php - 如何在不重新安装的情况下修复wamp服务器?

mysql - 对按标签过滤的项目进行排序

php - Laravel Eloquent 使用相同的外键获取多个记录

mysql - Seek 有助于加快我的 mysql 查询