SQL查询如何让它更快?

时间:2016-01-27 10:02:55

标签: mysql sql

我有一个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'

2 个答案:

答案 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中的数据。可能您需要将该列中的数据分发到多个列,以便您可以使用索引