我有一个SQL查询。是否有可能以某种方式更改此查询,因此它具有更好的性能,但结果相同?这个查询正在运行,但速度非常慢,我对改进其性能没有任何想法。
SELECT keyword, query
FROM url_alias ua
JOIN product p
on (p.manufacturer_id =
CONVERT(SUBSTRING_INDEX(ua.query,'=',-1),UNSIGNED INTEGER))
JOIN oc_product_to_storebk ps
on (p.product_id = ps.product_id)
AND ua.query LIKE 'manufacturer_id=%'
AND ps.store_id= '9'
GROUP BY ua.keyword
表格结构:
URL_ALIAS
+-----------------------------------------------+
| url_alias_id | query | keyword |
+--------------+---------------------+----------+
| 1 | manufacturer_id=100 | test |
+--------------+---------------------+----------+
产品
+-----------------+------------+
| manufacturer_id | product_id |
+-----------------+------------+
| 100 | 1000 |
+-----------------+------------+
OC_PRODUCT_TO_STOREBK
+------------+----------+
| product_id | store_id |
+------------+----------+
| 1000 | 9 |
+------------+----------+
当满足以下条件时,我想要 url_alias 关键字列中的所有关键字:LIKE 'manufacturer_id=%' AND ps.store_id='9'
答案 0 :(得分:1)
您应该避免使用convert
函数,因为它会很昂贵,并且无法从 url_alias 表中的索引中获利。
扩展 url_alias 表,使其具有查询部分的其他字段。你可能会犹豫不决,但是一旦完成它你就不会后悔。因此,您的 url_alias 表应如下所示:
create table url_alias (
url_alias_id int,
query varchar(200),
keyword varchar(100),
query_key varchar(200),
query_value_str varchar(200),
query_value_int int
);
如果您不想重新创建它,请按以下方式添加字段:
alter table url_alias add (
query_key varchar(200),
query_value_str varchar(200),
query_value_int int
);
使用此语句更新现有记录的这些新列(仅执行一次):
update url_alias
set query_key = substring_index(query, '=', 1),
query_value_str = substring_index(query, '=', -1),
query_value_int = nullif(
convert(substring_index(query,'=',-1),unsigned integer), 0);
然后创建一个触发器,以便在插入新记录时自动更新这3个额外字段:
create trigger ins_sum before insert on url_alias
for each row
set new.query_key = substring_index(new.query, '=', 1),
new.query_value_str = substring_index(new.query, '=', -1),
new.query_value_int = nullif(
convert(substring_index(new.query,'=',-1),unsigned integer), 0);
注意额外的 nullif(),当等号后的值不是数字时,它将确保最后一个字段为 null 。
如果您还更新了这些记录,那么还要创建一个类似的更新触发器。
通过此设置,您仍然可以像以前一样插入记录:
insert into url_alias (url_alias_id, query, keyword)
values (1, 'manufacturer_id=100', 'test');
当您选择此记录时,您会看到:
+--------------+---------------------+---------+-----------------+-----------------+-----------------+
| url_alias_id | query | keyword | query_key | query_value_str | query_value_int |
+--------------+---------------------+---------+-----------------+-----------------+-----------------+
| 1 | manufacturer_id=100 | test | manufacturer_id | 100 | 100 |
+--------------+---------------------+---------+-----------------+-----------------+-----------------+
现在提取和转换的工作已经完成一次,并且在选择记录时不必再重复。您可以像这样重写原始查询:
select ua.keyword, ua.query
from url_alias ua
join product p
on p.manufacturer_id = ua.query_value_int
join oc_product_to_storebk ps
on p.product_id = ps.product_id
and ua.query_key = 'manufacturer_id'
and ps.store_id = 9
group by ua.keyword, ua.query
现在,您可以通过在查询的两个元素上创建索引来提高性能:
create index query_key on url_alias(query_key, query_value_int, keyword);
在SQL计划使用之前,您可能需要进行一些实验以获取索引中的字段顺序。
请参阅此SQL fiddle。
答案 1 :(得分:0)
我假设您在store_id,product_id和关键字列上使用索引? 专注于更改数据模型以避免使用CONVERT和LIKE运算符。它们都会导致查询不会利用相关列的索引 另外,请仔细查看存储在ua.query colomn中的数据。可能您需要将该列中的数据分发到多个列,以便您可以使用索引