0

表:

  • 节点
  • 数据文本
  • 数据配置文件
  • 数据位置
  • 数据配置文件
  • 数据媒体
  • 数据产品
  • 数据元
  • 类别
  • 标签
  • 类别节点
  • 标签节点

这个问题是一个笼统的问题,在另一个问题的后面

解释:

每个“数据”表都有一个node_id指向节点表的 id(hasMany/belongsTo 关联)。

“节点”可以是任何东西——电视节目、电影、人物、文章……等等(全部通过 CMS 生成,因此用户可以控制他们想要的“节点”类型)。

提取数据时,我希望能够查询某些字段。例如,如果他们进行搜索,我希望能够拉出具有data_texts.title = '%george%'或按日期时间字段排序的节点data_locations

问题是,当我对所有七个数据表(或更多)进行连接时,查询必须命中如此多的组合行,以至于它只是超时(即使数据库几乎是空的....整个 200 行数据库)。

我意识到我可以根据我正在做的事情来确定我是否需要一个连接 - 但即使有五个或六个连接(一旦数据库达到 10k+ 条记录),它会非常慢,如果它完全有效的话。根据这个问题,我正在使用的查询只是对这些表进行连接完全超时。

每个节点可以具有每种数据类型的多行(出于多语言等原因)。

我完全被打败了——我正处于我认为我需要重组整个事情的地步,但没有时间去做。我曾考虑将所有内容合并到一张表中,但不确定如何....等


节点

CREATE TABLE `nodes` (
    `id` CHAR(36) NOT NULL,
    `name` VARCHAR(100) NOT NULL,
    `slug` VARCHAR(100) NOT NULL,
    `node_type_id` CHAR(36) NOT NULL,
    `site_id` CHAR(36) NOT NULL,
    `created` DATETIME NOT NULL,
    `modified` DATETIME NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `nodeTypeId` (`node_type_id`),
    INDEX `slug` (`slug`),
    INDEX `nodeId` (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM;

数据文本:

CREATE TABLE `data_texts` (
    `id` CHAR(36) NOT NULL,
    `title` VARCHAR(250) NULL DEFAULT NULL,
    `subtitle` VARCHAR(500) NULL DEFAULT NULL,
    `content` LONGTEXT NULL,
    `byline` VARCHAR(250) NULL DEFAULT NULL,
    `language_id` CHAR(36) NULL DEFAULT NULL,
    `foreign_key` CHAR(36) NULL DEFAULT NULL,
    `model` VARCHAR(40) NULL DEFAULT NULL,
    `node_id` CHAR(36) NULL DEFAULT NULL,
    `created` DATETIME NOT NULL,
    `modified` DATETIME NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `nodeId` (`node_id`),
    INDEX `languageId_nodeId` (`language_id`, `node_id`),
    INDEX `foreignKey_model` (`foreign_key`, `model`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

数据配置文件

CREATE TABLE `data_profiles` (
`id` CHAR(36) NOT NULL,
`name` VARCHAR(80) NULL DEFAULT NULL,
`email_personal` VARCHAR(100) NULL DEFAULT NULL,
`email_business` VARCHAR(100) NULL DEFAULT NULL,
`email_other` VARCHAR(100) NULL DEFAULT NULL,
`title` VARCHAR(100) NULL DEFAULT NULL,
`description` LONGTEXT NULL,
`prefix` VARCHAR(40) NULL DEFAULT NULL,
`phone_home` VARCHAR(40) NULL DEFAULT NULL,
`phone_business` VARCHAR(40) NULL DEFAULT NULL,
`phone_mobile` VARCHAR(40) NULL DEFAULT NULL,
`phone_other` VARCHAR(40) NULL DEFAULT NULL,
`foreign_key` CHAR(36) NULL DEFAULT NULL,
`model` VARCHAR(40) NULL DEFAULT NULL,
`node_id` CHAR(36) NULL DEFAULT NULL,
`language_id` CHAR(36) NULL DEFAULT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
`user_id` CHAR(36) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `nodeId` (`node_id`),
INDEX `languageId_nodeId` (`node_id`, `language_id`),
INDEX `foreignKey_model` (`foreign_key`, `model`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM;

类别

CREATE TABLE `categories` (
    `id` CHAR(36) NOT NULL,
    `name` VARCHAR(100) NOT NULL,
    `node_type_id` CHAR(36) NOT NULL,
    `site_id` CHAR(36) NOT NULL,
    `slug` VARCHAR(100) NOT NULL,
    `created` DATETIME NOT NULL,
    `modified` DATETIME NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `nodeTypeId` (`node_type_id`),
    INDEX `slug` (`slug`)
)
COMMENT='Used to categorize nodes'
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

类别节点

CREATE TABLE `categories_nodes` (
    `id` CHAR(36) NOT NULL,
    `category_id` CHAR(36) NOT NULL,
    `node_id` CHAR(36) NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `categoryId_nodeId` (`category_id`, `node_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

节点标签

CREATE TABLE `node_tags` (
    `id` CHAR(36) NOT NULL,
    `name` VARCHAR(40) NOT NULL,
    `site_id` CHAR(36) NOT NULL,
    `created` DATETIME NOT NULL,
    `modified` DATETIME NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `siteId` (`site_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

节点节点标签

CREATE TABLE `nodes_node_tags` (
    `id` CHAR(36) NOT NULL,
    `node_id` CHAR(36) NOT NULL,
    `node_tag_id` CHAR(36) NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `node_id_node_tag_id` (`node_id`, `node_tag_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

MySQL:

SELECT `Node`.`id`, `Node`.`name`, `Node`.`slug`, `Node`.`node_type_id`, `Node`.`site_id`, `Node`.`created`, `Node`.`modified`
FROM `mysite`.`nodes` AS `Node`
LEFT JOIN `mysite`.`data_date_times` AS `DataDateTime` ON (`DataDateTime`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_locations` AS `DataLocation` ON (`DataLocation`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_media` AS `DataMedia` ON (`DataMedia`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_metas` AS `DataMeta` ON (`DataMeta`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_profiles` AS `DataProfile` ON (`DataProfile`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_products` AS `DataProduct` ON (`DataProduct`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_texts` AS `DataText` ON (`DataText`.`node_id` = `Node`.`id`)
WHERE 1=1
GROUP BY `Node`.`id`

解释查询

4

2 回答 2

0

不幸的是,我现在无法进行任何测试。我只是抛出一些想法。我以后也许可以做一些测试。

  • 怀疑不同的排序规则。
  • 你的一些id是没用的。例如,您应该删除列 categories_nodes.id,并在 {category_id, node_id} 上放置一个主键约束。
  • 怀疑任何需要在运行时连接所有表的设计。有更好的方法。
  • 使用 innodb 和外键约束。
于 2012-09-19T14:57:34.620 回答
0

首先,尝试 InnoDB,而不是 MyISAM。

其次,删除 group by,看看它运行得如何,以及涉及多少行。应该不是很多,但很有趣。

您不需要节点上的“nodeId”索引(因为您已经将它作为主键)。再次,不应该有任何区别。

where 子句无关紧要。您可以以一种或另一种方式将其删除,但不会产生任何影响。

第三,好吧,有些东西严重坏了。

快速了解如何开始分析(例如http://dev.mysql.com/doc/refman/5.0/en/show-profile.html),然后运行 ​​profile 命令以查看所有时间的去向。如果它没有立即表明有什么东西坏了,就把它贴在这里。

于 2012-09-19T12:41:16.093 回答