简体   繁体   English

如何以有效的方式消除带有列表的 mysql 表中的冗余

[英]How to get rid of redundancy in a mysql table with lists in an efficient way

Some time ago I made a fast MVP that now has become a more realistic project.前段时间我做了一个快速的MVP ,现在已经成为一个更现实的项目。 Now I'm refactoring and improving it.现在我正在重构和改进它。 I have a table like this我有一张这样的桌子

CREATE TABLE `records` (
  `id` int(11) NOT NULL,
  `type` int(11) NOT NULL,
  .....
  `ref` int(11) DEFAULT NULL,
  `enabled` tinyint(1) NOT NULL DEFAULT '1',
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ALTER TABLE `mrecord`
  ADD PRIMARY KEY (`id`),
  ADD KEY `type` (`type`);
  ADD KEY `ref` (`ref`);

ref is a reference to a previous id or null if none and enabled lets me know if this item is the last version of the type. ref是对先前id或 null 的引用,如果没有并且enabled ,则让我知道该项目是否是该类型的最后一个版本。 The point is that when an item type X is replaced for a new one, the old one will be disabled ( enabled = 0) and the new one will set ref to the old one id .关键是,当一个项目类型 X 被替换为新项目时,旧项目将被禁用( enabled = 0),新项目将ref设置为旧项目id

For example, we have this table with 3 types of items:例如,我们有这张表,其中包含 3 种类型的项目:

 --------------------------------------------
| ID | type | other columns | ref  | enabled |
|--------------------------------------------|
| 1  |   1  |               | null |    1    |
| 2  |   2  |               | null |    1    |
| 3  |   3  |               | null |    1    |
 --------------------------------------------

and now we add a new item version that replaces item type 2:现在我们添加一个新的项目版本来替换项目类型 2:

 --------------------------------------------
| ID | type | other columns | ref  | enabled |
|--------------------------------------------|
| 1  |   1  |               | null |    1    |
| 2  |   2  |               | null |    0    |
| 3  |   3  |               | null |    1    |
| 4  |   2  |               |  2   |    1    |
 --------------------------------------------

and if we update the brand new item we have:如果我们更新我们拥有的全新项目:

 --------------------------------------------
| ID | type | other columns | ref  | enabled |
|--------------------------------------------|
| 1  |   1  |               | null |    1    |
| 2  |   2  |               | null |    0    |
| 3  |   3  |               | null |    1    |
| 4  |   2  |               |  2   |    0    |
| 5  |   2  |               |  4   |    1    |
 --------------------------------------------

What we have here are lists of item types with only last versions enabled.我们在这里拥有的是仅启用了最新版本的项目类型列表。

But here enabled column is redundant because an enabled item is just an item that has not a new version.但是这里enabled列是多余的,因为启用的项目只是一个没有新版本的项目。

So my problem is how to do a SQL query equivalent to:所以我的问题是如何做一个 SQL 查询相当于:

SELECT * FROM `records` WHERE type='2' AND enabled='1'

without using enabled and in an efficient way (this query is <1ms).不使用enabled和有效的方式(这个查询是<1ms)。

You can use not exists :您可以使用not exists

select  r.*
from records r
where not exists (select 1
                  from records r2
                  where r2.ref = r.id
                 ) and
       r.type = 2;

However, the use of enabled makes the code clearer, in my opinion.但是,在我看来, enabled使代码更清晰。 An index on records(ref) is needed for performance.性能需要records(ref)上的索引。

If you assumes that the ids are always incrementing, you could also use the largest id .如果您假设 id 总是递增,您也可以使用最大的id

For this query, you need an index on both columns that appear in the where clause:对于此查询,您需要在 where 子句中出现的两列上都有一个索引:

create index myidx on records(type, enabled);

With the index, the database should be able to execute the query efficiently.有了索引,数据库应该能够有效地执行查询。 You may also want to try inverting the columns order and see if it increases performance.您可能还想尝试反转列顺序,看看它是否会提高性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM