范围 SQL 查询是否会加快查询时间?
Does ranging the SQL query speed up the query time?
有一个 table words
包含 word
和 id
列和 50000 条记录。我知道 %XC%A
结构的单词在 id=30000
和 id=35000
之间。
现在考虑以下查询:
SELECT * FROM words WHERE word LIKE '%XCX%A'
和
SELECT * FROM words WHERE id>30000 and id < 35000 and word LIKE '%XCX%A'
从耗时的角度来看,它们之间有什么区别吗?
好吧,让我们找出来...
这是一个大约有 50000 个单词的数据集。一些单词(但仅在 30000 到 35000 范围内)遵循描述的模式:
EXPLAIN
SELECT * FROM words WHERE word LIKE '%XCX%A';
+----+-------------+-------+-------+---------------+------+---------+------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------+---------+------+-------+--------------------------+
| 1 | SIMPLE | words | index | NULL | word | 14 | NULL | 50976 | Using where; Using index |
+----+-------------+-------+-------+---------------+------+---------+------+-------+--------------------------+
EXPLAIN
SELECT * FROM words WHERE id>30000 and id < 35000 and word LIKE '%XCX%A';
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | words | range | PRIMARY | PRIMARY | 4 | NULL | 1768 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
我们可以看到第一个查询扫描了整个数据集(50976 行),而第二个查询只扫描给定 ID 之间的行(在我的示例中,ID 30000 和 35000 之间大约有 1768 行;有很多未使用的 ID,但这只是数据创建方式的副作用)。
因此,我们可以看到通过添加范围,MySQL 只需扫描(最坏情况下)数据集的五分之一(5000 行而不是 oof 50000 行)。这不会对这么小的数据集产生太大影响,但它会对数据集 100 或这个大小的 1000 倍产生影响。
需要注意的一点是,这两个查询将 return 相同的数据集(因为我们知道有效值只能在该 id 范围内找到),但它们不一定 return 数据集的顺序相同。为了保持一致性,您需要一个 ORDER BY 子句。
当然,要注意的另一件事是索引 word
没有意义(无论如何对于此查询),因为 '%...'
不能使用索引。
有一个 table words
包含 word
和 id
列和 50000 条记录。我知道 %XC%A
结构的单词在 id=30000
和 id=35000
之间。
现在考虑以下查询:
SELECT * FROM words WHERE word LIKE '%XCX%A'
和
SELECT * FROM words WHERE id>30000 and id < 35000 and word LIKE '%XCX%A'
从耗时的角度来看,它们之间有什么区别吗?
好吧,让我们找出来...
这是一个大约有 50000 个单词的数据集。一些单词(但仅在 30000 到 35000 范围内)遵循描述的模式:
EXPLAIN
SELECT * FROM words WHERE word LIKE '%XCX%A';
+----+-------------+-------+-------+---------------+------+---------+------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------+---------+------+-------+--------------------------+
| 1 | SIMPLE | words | index | NULL | word | 14 | NULL | 50976 | Using where; Using index |
+----+-------------+-------+-------+---------------+------+---------+------+-------+--------------------------+
EXPLAIN
SELECT * FROM words WHERE id>30000 and id < 35000 and word LIKE '%XCX%A';
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | words | range | PRIMARY | PRIMARY | 4 | NULL | 1768 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
我们可以看到第一个查询扫描了整个数据集(50976 行),而第二个查询只扫描给定 ID 之间的行(在我的示例中,ID 30000 和 35000 之间大约有 1768 行;有很多未使用的 ID,但这只是数据创建方式的副作用)。
因此,我们可以看到通过添加范围,MySQL 只需扫描(最坏情况下)数据集的五分之一(5000 行而不是 oof 50000 行)。这不会对这么小的数据集产生太大影响,但它会对数据集 100 或这个大小的 1000 倍产生影响。
需要注意的一点是,这两个查询将 return 相同的数据集(因为我们知道有效值只能在该 id 范围内找到),但它们不一定 return 数据集的顺序相同。为了保持一致性,您需要一个 ORDER BY 子句。
当然,要注意的另一件事是索引 word
没有意义(无论如何对于此查询),因为 '%...'
不能使用索引。