我正在编写一个脚本,列出所有12个类别中的25个项目。数据库结构如下:
tbl_items
---------------------------------------------
item_id | item_name | item_value | timestamp
---------------------------------------------
tbl_categories
-----------------------------
cat_id | item_id | timestamp
-----------------------------
表tbl_items
中有大约600,000行。我正在使用这个SQL查询:
SELECT e.item_id, e.item_value
FROM tbl_items AS e
JOIN tbl_categories AS cat WHERE e.item_id = cat.item_id AND cat.cat_id = 6001
LIMIT 25
在cat_id
的循环中使用相同的查询,从6000到6012.但我想要每个类别的最新记录。如果我使用类似的东西:
SELECT e.item_id, e.item_value
FROM tbl_items AS e
JOIN tbl_categories AS cat WHERE e.item_id = cat.item_id AND cat.cat_id = 6001
ORDER BY e.timestamp
LIMIT 25
..查询计算大约10分钟,这是不可接受的。我可以更好地使用LIMIT
来为每个类别提供最新的25条记录吗?
任何人都可以帮助我在没有ORDER BY
的情况下实现这一目标吗?任何想法或帮助将受到高度赞赏。
修改
tbl_items
+---------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+-------+
| item_id | int(11) | NO | PRI | 0 | |
| item_name | longtext | YES | | NULL | |
| item_value | longtext | YES | | NULL | |
| timestamp | datetime | YES | | NULL | |
+---------------------+--------------+------+-----+---------+-------+
tbl_categories
+----------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------+------+-----+---------+-------+
| cat_id | int(11) | NO | PRI | 0 | |
| item_id | int(11) | NO | PRI | 0 | |
| timestamp | datetime | YES | | NULL | |
+----------------+------------+------+-----+---------+-------+
答案 0 :(得分:1)
你能添加指数吗?如果您在timestamp
和其他相应列上添加索引,ORDER BY
将不会花费10分钟。
答案 1 :(得分:1)
首先:
似乎是items
和categories
之间的N:M关系:item
可能在几个categories
中。我这样说是因为categories
有item_id
个外键。
如果不是N:M关系,那么你应该考虑改变设计。如果它是1:N关系,其中类别包含多个项目,则item
必须保留category_id
个外键。
使用N:M:
我已经重写了你的查询以使内部联接成为交叉联接:
SELECT e.item_id, e.item_value
FROM
tbl_items AS e
JOIN
tbl_categories AS cat
on e.item_id = cat.item_id
WHERE
cat.cat_id = 6001
ORDER BY
e.timestamp
LIMIT 25
要优化所需的性能索引是:
create index idx_1 on tbl_categories( cat_id, item_id)
它不是必需的项目索引,因为主键也被索引。
包含时间戳的索引没有帮助作为mutch。确保可以尝试使用item_id
和timestamp
的项目的索引来避免访问表并从索引中获取值:
create index idx_2 on tbl_items( item_id, timestamp)
要提高性能,您可以通过单个查询更改类别循环:
select T.cat_id, T.item_id, T.item_value from
(SELECT cat.cat_id, e.item_id, e.item_value
FROM
tbl_items AS e
JOIN
tbl_categories AS cat
on e.item_id = cat.item_id
ORDER BY
e.timestamp
LIMIT 25
) T
WHERE
T.cat_id between 6001 and 6012
ORDER BY
T.cat_id, T.item_id
请尝试此查询,并在必要时回复您的评论以进行优化。
答案 2 :(得分:1)
除了所有其他因素外,我可以告诉您查询速度太慢的主要原因是因为结果涉及longtext
列。
BLOB
和TEXT
字段主要用于存储完整的文件,文本或二进制文件。它们与InnoDB表的行数据分开存储。每次查询involes排序(显式或group by
)时,MySQL肯定会使用磁盘进行排序(因为它无法提前确定任何文件的大小)。
这可能是一条经验法则:如果您需要在查询中返回多行的一行,那么该字段的类型几乎不应该是TEXT
或BLOB
,请改用VARCHAR
或VARBINARY
。
<强> UPD 强>
如果无法更新表,则使用当前索引和列类型的查询几乎不会很快。但是,无论如何,这是一个类似的问题,也是您问题的流行解决方案:How to SELECT the newest four items per category?