【发布时间】:2017-03-14 06:32:39
【问题描述】:
我有一个查询,在 WHERE 子句中添加了几个列值。我无法在单个列中预先计算此添加,因为要使用的列组合因查询而异。我的问题是我的表很大(几亿行),性能很差。
示例表:
+---------+------------+--------+--------+--------+--------+
| tableId | categoryId | value1 | value2 | value3 | value4 |
+---------+------------+--------+--------+--------+--------+
| 1 | 1 | 1 | 0 | 5 | 7 |
| 2 | 1 | 8 | 1 | 7 | 0 |
| 3 | 1 | 10 | 5 | 0 | 20 |
| 4 | 2 | 0 | 15 | 0 | 22 |
| 5 | 2 | 20 | 0 | 11 | 0 |
+---------+------------+--------+--------+--------+--------+
查询示例:
SELECT * FROM myTable WHERE categoryId = 1 AND (value1 + value2 + value3 + value4) > 9;
SELECT * FROM myTable WHERE categoryId = 1 AND (value1 + value3 + value4) > 5;
提高此类查询性能的最佳策略是什么? (编辑:我已经在categoryId 上有一个索引,这没有帮助)
对此类查询使用索引是否有帮助?然后我是否必须为所有可能的列组合创建所有可能的索引?生成的索引会不会非常非常大?
ALTER TABLE myTable
ADD INDEX(categoryId, value1),
ADD INDEX(categoryId, value2),
ADD INDEX(categoryId, value3),
ADD INDEX(categoryId, value4),
ADD INDEX(categoryId, value1, value2),
ADD INDEX(categoryId, value1, value3),
ADD INDEX(categoryId, value1, value4),
etc
或者可能创建一个链接表,其中布尔值字段指定使用了哪些列?但这会导致一个包含数十亿行的表,不确定这是否更好......
+---------+-----------+-----------+-----------+-----------+----------+
| tableId | useValue1 | useValue2 | useValue3 | useValue4 | valueSum |
+---------+-----------+-----------+-----------+-----------+----------+
| 1 | 1 | 1 | 1 | 1 | 13 |
| 1 | 1 | 1 | 1 | 0 | 6 |
| 1 | 1 | 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 0 | 1 | 8 |
| 1 | 1 | 0 | 1 | 1 | 13 |
| 1 | 1 | 0 | 1 | 0 | 6 |
| 1 | 1 | 0 | 0 | 0 | 1 |
| 1 | 1 | 0 | 0 | 1 | 8 |
| 1 | 0 | 1 | 1 | 1 | 12 |
| 1 | 0 | 1 | 1 | 0 | 5 |
| 1 | 0 | 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 0 | 1 | 7 |
| 1 | 0 | 0 | 1 | 1 | 12 |
| 1 | 0 | 0 | 1 | 0 | 5 |
| 1 | 0 | 0 | 0 | 1 | 7 |
+---------+-----------+-----------+-----------+-----------+----------+
带索引:
ALTER TABLE linkTable INDEX(tableId, useValue1, useValue2, useValue3, useValue4, valueSum);
还有其他想法吗?
【问题讨论】:
-
如果没有您的数据实际是什么,谁能弄清楚!!!!
-
@e4c5:我同意,我可以再发一篇文章来质疑整个工作流程、计算、输出和存储。但这就是我今天必须处理的事情:) 你觉得我的第二个想法怎么样?
-
枚举列是设计不佳的症状 - 这反过来会影响性能
-
也许可以试试 MySQL 的列存储引擎?像 ICE 或 InfiniDB。您不需要索引,因为它们存储的数据类似于基于行的存储索引。这种类型的存储在某些用例中运行速度更快,而在其他用例中运行速度较慢。
-
@e4c5:好的,按照你的说法,我在另一个问题中描述了我的实际问题:stackoverflow.com/q/42781299/1768736
标签: mysql sql indexing sqlperformance