Как настроиться, MySQL с 7 соединениями таблицы считают запрос, где таблицы содержат 30,000 + строки?

У меня есть запрос SQL, который считает количество результатов для сложного запроса. Фактический запрос Select очень быстр при ограничении 20 результатами, но версия количества занимает приблизительно 4,5 секунды на моих текущих таблицах после большой оптимизации.

Если я удаляю два соединения и где пункты на тегах сайта и тегах галереи, запрос работает в 1,5 секунды. Если я создаю 3 отдельных запроса - один для выбора сайтов платы, один для выбора имен и один для сплачивания всего - я могу свалить запрос к.6 секундам, который все еще не достаточно хорош. Это также вынудило бы меня использовать хранимую процедуру, так как я должен буду сделать в общей сложности 4 запроса в, в спящем режиме.

Для запроса, "как", вот некоторая информация:

Handler_read_key 1746669
Handler_read_next 1546324

Таблица галереи имеет 40 000 строк
Таблица сайта имеет 900 строк
Таблица имени имеет 800 строк
Таблица тега имеет 3 560 строк

Я довольно плохо знаком с MySQL и настройкой, и у меня есть индексы на:

  • столбец 'термина' в таблице тега
  • 'опубликованный' столбец в таблице галереи
  • 'значение' для таблицы имени

Я надеюсь получать этот запрос к 0,1 миллисекундам.

SELECT count(distinct gallery.id)
from gallery gallery 
    inner join
        site site 
            on gallery.site_id = site.id 
    inner join
        site_to_tag p2t 
            on site.id = p2t.site_id 
    inner join
        tag site_tag 
            on p2t.tag_id = site_tag.id 
    inner join
        gallery_to_name g2mn 
            on gallery.id = g2mn.gallery_id 
    inner join
        name name 
            on g2mn.name_id = name.id 
    inner join
        gallery_to_tag g2t 
            on gallery.id = g2t.gallery_id 
    inner join
        tag tag 
            on g2t.tag_id = tag.id
where
    gallery.published = true and (
        name.value LIKE 'sometext%' or
        tag.term = 'sometext' or 
        site.`name` like 'sometext%' or
        site_tag.term = 'sometext'
    )

Объясните данные:

| id | select_type | table        | type   | possible_keys                                                     | key                | key_len | ref                                       | rows | Extra                              |
+----+-------------+--------------+--------+-------------------------------------------------------------------+--------------------+---------+-------------------------------------------+------+------------------------------------+
|  1 | SIMPLE      | site         | index  | PRIMARY,nameIndex                                                 | nameIndex          | 258     | NULL                                      |  950 | Using index; Using temporary       |
|  1 | SIMPLE      | gallery      | ref    | PRIMARY,publishedIndex,FKF44C775296EECE37,publishedSiteIdIndex    | FKF44C775296EECE37 | 9       | production.site.id                        |   20 | Using where                        |
|  1 | SIMPLE      | g2mn         | ref    | PRIMARY,FK3EFFD7F8AFAD7A5E,FK3EFFD7F832C04188                     | FK3EFFD7F8AFAD7A5E | 8       | production.gallery.id                     |    1 | Using index; Distinct              |
|  1 | SIMPLE      | name         | eq_ref | PRIMARY,valueIndex                                                | PRIMARY            | 8       | production.g2mn.name_id                   |    1 | Distinct                           |
|  1 | SIMPLE      | g2t          | ref    | PRIMARY,FK3DDB4D63AFAD7A5E,FK3DDB4D63E210FBA6                     | FK3DDB4D63AFAD7A5E | 8       | production.g2mn.gallery_id                |    2 | Using where; Using index; Distinct |
|  1 | SIMPLE      | tag          | eq_ref | PRIMARY,termIndex                                                 | PRIMARY            | 8       | production.g2t.tag_id                     |    1 | Distinct                           |
|  1 | SIMPLE      | p2t          | ref    | PRIMARY,FK29424AB796EECE37,FK29424AB7E210FBA6                     | PRIMARY            | 8       | production.gallery.site_id                |    3 | Using where; Using index; Distinct |
|  1 | SIMPLE      | site_tag     | eq_ref | PRIMARY,termIndex                                                 | PRIMARY            | 8       | production.p2t.tag_id                     |    1 | Using where; Distinct              |
+----+-------------+--------------+--------+-------------------------------------------------------------------+--------------------+---------+-------------------------------------------+------+------------------------------------+

Отдельные скорости количества:

[SQL] select count(*) from gallery;
Affected rows: 0
Time: 0.014ms
Results: 40385

[SQL] 
select count(*) from gallery_to_name;
Affected rows: 0
Time: 0.012ms
Results: 35615

[SQL] 
select count(*) from gallery_to_tag;
Affected rows: 0
Time: 0.055ms
Results: 165104

[SQL] 
select count(*) from tag;
Affected rows: 0
Time: 0.002ms
Results: 3560    

[SQL] 
select count(*) from site;
Affected rows: 0
Time: 0.001ms
Results: 901

[SQL] 
select count(*) from site_to_tag;
Affected rows: 0
Time: 0.003ms
Results: 7026
9
задан halfer 4 August 2017 в 08:33
поделиться

6 ответов

Я включил свою тестовую схему и сценарий для создания тестовых данных в конце этого поста. Я использовал параметр SQL_NO_CACHE , чтобы MySQL не кэшировал результаты запросов - это только для тестирования и в конечном итоге должно быть удалено.

Это идея, аналогичная предложенной Донни, но я немного привел ее в порядок. Если я правильно понял объединения, нет необходимости повторять все объединения при каждом выборе, поскольку каждое фактически независимо от других. Исходный пункт WHERE оговаривает, что gallery.published должен быть истинным, а затем следует ряд из 4 условий, соединенных OR . Таким образом, каждый запрос может выполняться отдельно. Вот четыре соединения:

gallery <--> gallery_to_name <--> name
gallery <--> gallery_to_tag <--> tag
gallery <--> site
gallery <--> site <--> site_to_tag <--> tag

Поскольку галерея содержит site_id , в этом случае нет необходимости в промежуточном соединении через таблицу site . Таким образом, последнее соединение может быть сокращено до следующего:

gallery <--> site_to_tag <--> tag

Выполнение каждого SELECT отдельно и использование UNION для объединения результатов выполняется очень быстро. Результаты здесь предполагают структуры таблиц и индексы , показанные в конце этого сообщения:

SELECT SQL_NO_CACHE COUNT(id) AS matches FROM (
   (SELECT g.id
    FROM gallery AS g
    INNER JOIN site AS s ON s.id = g.site_id
    WHERE g.published = TRUE AND s.name LIKE '3GRD%')
UNION
   (SELECT g.id
    FROM gallery AS g
    INNER JOIN gallery_to_name AS g2n ON g2n.gallery_id = g.id
    INNER JOIN name AS n ON n.id = g2n.name_id
    WHERE g.published = TRUE AND n.value LIKE '3GRD%')
UNION
   (SELECT g.id
    FROM gallery AS g
    INNER JOIN gallery_to_tag  AS g2t ON g2t.gallery_id = g.id
    INNER JOIN tag AS gt  ON gt.id = g2t.tag_id
    WHERE g.published = TRUE AND gt.term = '3GRD')
UNION
   (SELECT g.id
    FROM gallery AS g
    INNER JOIN site_to_tag AS s2t ON s2t.site_id = g.site_id
    INNER JOIN tag AS st  ON st.id = s2t.tag_id
    WHERE g.published = TRUE AND st.term = '3GRD')
) AS totals;

+---------+
| matches |
+---------+
|      99 |
+---------+
1 row in set (0.00 sec)

Скорость действительно зависит от критериев поиска. В следующем примере для каждой таблицы используется различное значение поиска, и оператору LIKE нужно проделать немного больше работы, поскольку теперь существует больше потенциальных совпадений для каждой:

SELECT SQL_NO_CACHE COUNT(id) AS matches FROM (
   (SELECT g.id
    FROM gallery AS g
    INNER JOIN site AS s ON s.id = g.site_id
    WHERE g.published = TRUE AND s.name LIKE '3H%')
UNION
   (SELECT g.id
    FROM gallery AS g
    INNER JOIN gallery_to_name AS g2n ON g2n.gallery_id = g.id
    INNER JOIN name AS n ON n.id = g2n.name_id
    WHERE g.published = TRUE AND n.value LIKE '3G%')
UNION
   (SELECT g.id
    FROM gallery AS g
    INNER JOIN gallery_to_tag  AS g2t ON g2t.gallery_id = g.id
    INNER JOIN tag AS gt  ON gt.id = g2t.tag_id
    WHERE g.published = TRUE AND gt.term = '3IDP')
UNION
   (SELECT g.id
    FROM gallery AS g
    INNER JOIN site_to_tag AS s2t ON s2t.site_id = g.site_id
    INNER JOIN tag AS st  ON st.id = s2t.tag_id
    WHERE g.published = TRUE AND st.term = '3OJX')
) AS totals;

+---------+
| matches |
+---------+
|   12505 |
+---------+
1 row in set (0.24 sec)

Эти результаты выгодно отличаются от результатов запроса, который использует несколько объединений:

SELECT SQL_NO_CACHE COUNT(DISTINCT g.id) AS matches
FROM gallery AS g
INNER JOIN gallery_to_name AS g2n ON g2n.gallery_id = g.id
INNER JOIN name            AS n   ON n.id = g2n.name_id
INNER JOIN gallery_to_tag  AS g2t ON g2t.gallery_id = g.id
INNER JOIN tag             AS gt  ON gt.id = g2t.tag_id
INNER JOIN site            AS s   ON s.id = g.site_id
INNER JOIN site_to_tag     AS s2t ON s2t.site_id = s.id
INNER JOIN tag             AS st  ON st.id = s2t.tag_id
WHERE g.published = TRUE AND (
    gt.term = '3GRD' OR
    st.term = '3GRD' OR
    n.value LIKE '3GRD%' OR
    s.name LIKE '3GRD%');

+---------+
| matches |
+---------+
|      99 |
+---------+
1 row in set (2.62 sec)

SELECT SQL_NO_CACHE COUNT(DISTINCT g.id) AS matches
FROM gallery AS g
INNER JOIN gallery_to_name AS g2n ON g2n.gallery_id = g.id
INNER JOIN name            AS n   ON n.id = g2n.name_id
INNER JOIN gallery_to_tag  AS g2t ON g2t.gallery_id = g.id
INNER JOIN tag             AS gt  ON gt.id = g2t.tag_id
INNER JOIN site            AS s   ON s.id = g.site_id
INNER JOIN site_to_tag     AS s2t ON s2t.site_id = s.id
INNER JOIN tag             AS st  ON st.id = s2t.tag_id
WHERE g.published = TRUE AND (
    gt.term = '3IDP' OR
    st.term = '3OJX' OR
    n.value LIKE '3G%' OR
    s.name LIKE '3H%');

+---------+
| matches |
+---------+
|   12505 |
+---------+
1 row in set (3.17 sec)

SCHEMA
Важны индексы столбцов id плюс site.name , name.value и tag.term :

DROP SCHEMA IF EXISTS `egervari`;
CREATE SCHEMA IF NOT EXISTS `egervari`;
USE `egervari`;

-- -----------------------------------------------------
-- Table `site`
-- -----------------------------------------------------

DROP TABLE IF EXISTS `site` ;
CREATE  TABLE IF NOT EXISTS `site` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(255) NOT NULL ,
  INDEX `name` (`name` ASC) ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `gallery`
-- -----------------------------------------------------

DROP TABLE IF EXISTS `gallery` ;
CREATE  TABLE IF NOT EXISTS `gallery` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `site_id` INT UNSIGNED NOT NULL ,
  `published` TINYINT(1) NOT NULL DEFAULT 0 ,
  PRIMARY KEY (`id`) ,
  INDEX `fk_gallery_site` (`site_id` ASC) ,
  CONSTRAINT `fk_gallery_site`
    FOREIGN KEY (`site_id` )
    REFERENCES `site` (`id` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `name`
-- -----------------------------------------------------

DROP TABLE IF EXISTS `name` ;
CREATE  TABLE IF NOT EXISTS `name` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `value` VARCHAR(255) NOT NULL ,
  INDEX `value` (`value` ASC) ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `tag`
-- -----------------------------------------------------

DROP TABLE IF EXISTS `tag` ;
CREATE  TABLE IF NOT EXISTS `tag` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `term` VARCHAR(255) NOT NULL ,
  INDEX `term` (`term` ASC) ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `gallery_to_name`
-- -----------------------------------------------------

DROP TABLE IF EXISTS `gallery_to_name` ;
CREATE  TABLE IF NOT EXISTS `gallery_to_name` (
  `gallery_id` INT UNSIGNED NOT NULL ,
  `name_id` INT UNSIGNED NOT NULL ,
  PRIMARY KEY (`gallery_id`, `name_id`) ,
  INDEX `fk_gallery_to_name_gallery` (`gallery_id` ASC) ,
  INDEX `fk_gallery_to_name_name` (`name_id` ASC) ,
  CONSTRAINT `fk_gallery_to_name_gallery`
    FOREIGN KEY (`gallery_id` )
    REFERENCES `gallery` (`id` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `fk_gallery_to_name_name`
    FOREIGN KEY (`name_id` )
    REFERENCES `name` (`id` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `gallery_to_tag`
-- -----------------------------------------------------

DROP TABLE IF EXISTS `gallery_to_tag` ;
CREATE  TABLE IF NOT EXISTS `gallery_to_tag` (
  `gallery_id` INT UNSIGNED NOT NULL ,
  `tag_id` INT UNSIGNED NOT NULL ,
  PRIMARY KEY (`gallery_id`, `tag_id`) ,
  INDEX `fk_gallery_to_tag_gallery` (`gallery_id` ASC) ,
  INDEX `fk_gallery_to_tag_tag` (`tag_id` ASC) ,
  CONSTRAINT `fk_gallery_to_tag_gallery`
    FOREIGN KEY (`gallery_id` )
    REFERENCES `gallery` (`id` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `fk_gallery_to_tag_tag`
    FOREIGN KEY (`tag_id` )
    REFERENCES `tag` (`id` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `site_to_tag`
-- -----------------------------------------------------

DROP TABLE IF EXISTS `site_to_tag` ;
CREATE  TABLE IF NOT EXISTS `site_to_tag` (
  `site_id` INT UNSIGNED NOT NULL ,
  `tag_id` INT UNSIGNED NOT NULL ,
  PRIMARY KEY (`site_id`, `tag_id`) ,
  INDEX `fk_site_to_tag_site` (`site_id` ASC) ,
  INDEX `fk_site_to_tag_tag` (`tag_id` ASC) ,
  CONSTRAINT `fk_site_to_tag_site`
    FOREIGN KEY (`site_id` )
    REFERENCES `site` (`id` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `fk_site_to_tag_tag`
    FOREIGN KEY (`tag_id` )
    REFERENCES `tag` (`id` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;

] ТЕСТОВЫЕ ДАННЫЕ
Заполняются сайт 900 строками, тег 3560 строками, имя 800 строками и галерея 40 000 строк и вставляет записи в таблицы ссылок:

DELIMITER //
DROP PROCEDURE IF EXISTS populate//
CREATE PROCEDURE populate()
BEGIN
    DECLARE i INT DEFAULT 0;

    WHILE i < 900 DO
        INSERT INTO site (name) VALUES (CONV(i + 1 * 10000, 20, 36));
        SET i = i + 1;
    END WHILE;

    SET i = 0;
    WHILE i < 3560 DO
        INSERT INTO tag (term) VALUES (CONV(i + 1 * 10000, 20, 36));
        INSERT INTO site_to_tag (site_id, tag_id) VALUES ( (i MOD 900) + 1, i + 1 );
        SET i = i + 1;
    END WHILE;

    SET i = 0;
    WHILE i < 800 DO
        INSERT INTO name (value) VALUES (CONV(i + 1 * 10000, 20, 36));
        SET i = i + 1;
    END WHILE;

    SET i = 0;
    WHILE i < 40000 DO    
        INSERT INTO gallery (site_id, published) VALUES ( (i MOD 900) + 1, i MOD 2 );
        INSERT INTO gallery_to_name (gallery_id, name_id) VALUES ( i + 1, (i MOD 800) + 1 );
        INSERT INTO gallery_to_tag (gallery_id, tag_id) VALUES ( i + 1, (i MOD 3560) + 1 );
        SET i = i + 1;
    END WHILE;
END;
//
DELIMITER ;
CALL populate();
9
ответ дан 2 November 2019 в 23:59
поделиться

Похоже, что ваше предложение WHERE может быть нарушителем, особенно следующее:

lower(name2_.value) like ?

Согласно документации MySQL :

Значение по умолчанию набор символов и сопоставление - latin1 и latin1_swedish_ci, поэтому небинарные сравнения строк по умолчанию нечувствительны к регистру.

Возможно, вам не понадобится функция LOWER () в предложении WHERE. Функции в левой части сравнения предотвращают использование индексов.

Как выглядят ваши значения LIKE ? Если вы используете подстановочный знак слева от значения, это предотвращает использование индексов.

Попробуйте заменить ваши операторы OR на UNION .

Попробуйте выполнить запрос без DISTINCT , чтобы увидеть, насколько это влияет на ваш запрос.

1
ответ дан 2 November 2019 в 23:59
поделиться

Счетчики часто бывают медленными, так как они требуют выборки всех данных, возвращаемых курсором, чтобы выяснить, сколько строк будет фактически извлечено.

Сколько времени нужно для подсчета каждой отдельной таблицы? Сложите общее время - если оно больше 0,1 миллисекунды, я не думаю, что вы сможете заставить запрос выполняться так быстро, как вам хотелось бы. Что касается способов его ускорения, вы можете попробовать вставить некоторые из критериев предложения WHERE в подвыборку, как в

select 
    count(distinct this_.id) as y0_  
from 
    (select * from gallery where published=?) this_  
inner join 
    site site3_  
        on this_.site_id=site3_.id  
inner join 
    site_to_tag list7_  
        on site3_.id=list7_.site_id  
inner join 
    tag sitetag4_  
        on list7_.tag_id=sitetag4_.id  
inner join 
    gallery_to_name names9_  
        on this_.id=names9_.gallery_id  
inner join 
    name name2_  
        on names9_.name_id=name2_.id  
inner join 
    gallery_to_tag list11_  
        on this_.id=list11_.gallery_id  
inner join 
    tag tag1_  
    on list11_.tag_id=tag1_.id  
where lower(name2_.value) like ? or 
      tag1_.term=? or
      lower(site3_.name) like ? or
      lower(this_.description) like ? or
      sitetag4_.term=?

. Сколько полей находится в каждой из этих таблиц? Можете ли вы использовать подвыборки, чтобы сократить объем данных, которые база данных должна объединить, или вам действительно нужны все столбцы?

Наличие трех предикатов LIKE замедлит работу, как и использование функции LOWER в предложении WHERE. Если вам нужно выполнять сравнение без учета регистра, может быть лучше иметь два поля, одно в «нормальном» (как введено) регистре и одно, хранящееся в нижнем (или ВЕРХНЕМ) регистре, для выполнения нечувствительного поиска. Вы можете использовать триггер, чтобы синхронизировать нижний / верхний вариант с версией «нормального» регистра.

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ:

Глядя на вывод EXPLAIN PLAN, не видно, что поля, используемые в вашем предложении WHERE, проиндексированы - или, по крайней мере, кажется, что индексы не используются. Это может быть побочным продуктом всех предикатов ИЛИ в WHERE. Если эти поля не проиндексированы, вы можете попробовать их проиндексировать.

1
ответ дан 2 November 2019 в 23:59
поделиться

ИЛИ снижает производительность запроса даже при хороших индексах. Чем больше таблицы, тем хуже.

Это ужасно некрасиво, но, вероятно, будет быстрее (очевидно, за счет удобочитаемости). Если бы MySQL поддерживал только CTE, это было бы намного проще.

Вы также можете написать короткий пакет и выбрать общую часть повторяющегося запроса во временную таблицу, а затем выполнить все действия в соответствии с временной таблицей. Возможно, вам придется индексировать временную таблицу, а может и нет, чтобы это сработало, на самом деле это зависит от количества строк.

(Обратите внимание, что union уже выполняет отдельный , поэтому нет необходимости делать это снова, подсчет и принудительно выполнять другой вид)

select
  count(id)   
from (
SELECT gallery.id
from gallery gallery 
    inner join
        site site 
          on gallery.site_id = site.id 
    inner join
        site_to_tag p2t 
            on site.id = p2t.site_id 
    inner join
        tag site_tag 
            on p2t.tag_id = site_tag.id 
    inner join
        gallery_to_name g2mn 
            on gallery.id = g2mn.gallery_id 
    inner join
        name name 
            on g2mn.name_id = name.id 
    inner join
        gallery_to_tag g2t 
            on gallery.id = g2t.gallery_id 
    inner join
        tag tag 
            on g2t.tag_id = tag.id
where
    gallery.published = true and name.value like 'sometext%'
UNION
SELECT gallery.id
from gallery gallery 
    inner join
        site site 
          on gallery.site_id = site.id 
    inner join
        site_to_tag p2t 
            on site.id = p2t.site_id 
    inner join
        tag site_tag 
            on p2t.tag_id = site_tag.id 
    inner join
        gallery_to_name g2mn 
            on gallery.id = g2mn.gallery_id 
    inner join
        name name 
            on g2mn.name_id = name.id 
    inner join
        gallery_to_tag g2t 
            on gallery.id = g2t.gallery_id 
    inner join
        tag tag 
            on g2t.tag_id = tag.id
where
    gallery.published = true and tag.term = 'sometext'
UNION
SELECT gallery.id
from gallery gallery 
    inner join
        site site 
          on gallery.site_id = site.id 
    inner join
        site_to_tag p2t 
            on site.id = p2t.site_id 
    inner join
        tag site_tag 
            on p2t.tag_id = site_tag.id 
    inner join
        gallery_to_name g2mn 
            on gallery.id = g2mn.gallery_id 
    inner join
        name name 
            on g2mn.name_id = name.id 
    inner join
        gallery_to_tag g2t 
            on gallery.id = g2t.gallery_id 
    inner join
        tag tag 
            on g2t.tag_id = tag.id
where
    gallery.published = true and site.`name` like 'sometext%'
UNION
SELECT gallery.id
from gallery gallery 
    inner join
        site site 
          on gallery.site_id = site.id 
    inner join
        site_to_tag p2t 
            on site.id = p2t.site_id 
    inner join
        tag site_tag 
            on p2t.tag_id = site_tag.id 
    inner join
        gallery_to_name g2mn 
            on gallery.id = g2mn.gallery_id 
    inner join
        name name 
            on g2mn.name_id = name.id 
    inner join
        gallery_to_tag g2t 
            on gallery.id = g2t.gallery_id 
    inner join
        tag tag 
            on g2t.tag_id = tag.id
where
    gallery.published = true and site_tag.term = 'sometext'
) as x
1
ответ дан 2 November 2019 в 23:59
поделиться

Признаюсь, я не нашел времени, чтобы полностью разобраться в ваших таблицах и запросах. Однако, учитывая требуемое время ответа и очевидную сложность текущих предложений, я бы сказал, что это одна из тех ситуаций, когда (вместо того, чтобы просить SQL подсчитать все записи, которые я хочу подсчитать), я Я буду вести отдельную таблицу всегда актуальных подсчетов и всегда обновлять любые соответствующие подсчеты с помощью инициированного кода при добавлении / изменении / удалении любой записи.

Например, представьте себе файл транзакции с миллионом строк, и мне нужна сумма поля 2. Я могу попросить базу данных выполнить SUM () для поля, или я могу сохранить отдельную сумму для поля 2 в таблице где-нибудь, что корректируется каждый раз, когда запись добавляется, удаляется или редактируется поле 2. Это избыточно, но очень быстро, когда я хочу узнать общую сумму. И я всегда могу SUM (), если я хочу проверить свою отдельную вычисленную сумму.

0
ответ дан 2 November 2019 в 23:59
поделиться

Хм ... просто просматриваю ваше сообщение в течение двух минут, так что мой ответ может быть не идеальным ... но вы не думали о введении индексной таблицы, которая ссылается на другие объекты?

как

CREATE  TABLE `references`
  `text` VARC>HAR(...) NOT NULL,
  `name` VARCHAR(255) NOT NULL,
  `reference_type` WHATEVER, // enum or what suits your needs
  `reference_id` INTEGER NOT NULL
);

Тогда просто запросите эту таблицу:

SELECT COUNT(*) FROM references WHERE sometext LIKE ...;

Придется обрабатывать случаи с 'sometext%', хотя ...

Кроме того, действительно ли важно количество галерей, или ваш запрос предназначен только для проверить, существует ли хоть один?

0
ответ дан 2 November 2019 в 23:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: