颜色搜索数据库设计模式

时间:2016-05-23 21:39:59

标签: php mysql

我正在使用php和mysql构建一个颜色搜索功能。搜索的要求是它需要快速,而不是使用连接,并允许1-5个十六进制颜色输入查询数据库并返回“最准确”的结果。 “最准确”是指结果将反映搜索输入。我有一些数据可以帮助你,例如映射的颜色值(映射到预定义颜色数组)与原始搜索输入十六进制值(例如ff0000)之间的距离。

颜色搜索引擎的工作方式是输入1-5个十六进制值(例如#ff0000,#000000,#9ef855等),点击搜索,然后搜索数据库以查找包含最高百分比的图像那些颜色。有关颜色搜索引擎的工作原理,请参阅this color search注意:我构建了这个,但是它有一个完全不同的模式,它有缩放问题而且无法添加索引,因为颜色的数量与表列的数量直接相关,即120.建议我使用我所拥有的现在已经无法建立。

数据库中的数据来自对图像的测量。从图像中提取最多5种颜色,然后将每个十六进制颜色值(hex)映射到最接近的预定义十六进制值(map_hex)。这两个数据以及以下数据都存储在数据库中:

  • media_id
  • hex(来自图像测量的实际真实值)
  • map_hex(前一个十六进制值的映射值)
  • 百分比(图片中找到的此颜色的数量)
  • 距离(真实十六进制值与映射的十六进制值之间的距离)
  • sequence(unix timestamp,for ordering)

在将颜色搜索查询发送到数据库之前,它会映射到一组颜色,以便我们可以使用映射在map_hex上进行直接查找。这对我来说似乎比尝试进行范围类型的查询更快。

截至目前,我正在尝试两种数据库设计模式,但两者似乎都有自己的问题。

架构1

CREATE TABLE `media_has_colors` (
  `media_id` int(9) unsigned NOT NULL,
  `hex` varchar(6) NOT NULL DEFAULT '',
  `map_hex` varchar(6) NOT NULL,
  `percentage` double unsigned NOT NULL,
  `distance` double unsigned NOT NULL,
  `sequence` int(11) unsigned NOT NULL,
  PRIMARY KEY (`media_id`,`hex`),
  KEY `index_on_hex` (`hex`),
  KEY `index_on_percentage` (`percentage`),
  KEY `index_on_timestamp` (`sequence`),
  KEY `index_on_media_id` (`media_id`),
  KEY `index_on_mapping_distance` (`distance`),
  KEY `index_on_mapping_hex` (`map_hex`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

示例查询:

SELECT sql_no_cache media_id, hex, map_hex, distance,
    avg(percentage) as percentage,
    SUM((IF(map_hex = '61615a',1,0)) + (IF(map_hex = '34362d',1,0)) + (IF(map_hex = 'dbd5dd',1,0))) as matchCount
FROM media_has_colors 
WHERE map_hex = '61615a' or map_hex = '34362d' or map_hex = 'dbd5dd'
GROUP BY media_id
ORDER BY matchCount DESC, distance, percentage DESC
LIMIT 100;

我在架构1中看到的第一个问题是我被迫使用group bysum。我承认我还没有测试过大量的记录,但似乎它可能会变慢。最重要的是,我无法确定哪些map_hex值匹配(这就是为什么我要尝试使用matchCount

架构2

CREATE TABLE `media_has_colors` (
  `media_id` int(9) unsigned NOT NULL,
  `color_1_hex` varchar(6) NOT NULL DEFAULT '',
  `color_2_hex` varchar(6) NOT NULL DEFAULT '',
  `color_3_hex` varchar(6) NOT NULL DEFAULT '',
  `color_4_hex` varchar(6) NOT NULL DEFAULT '',
  `color_5_hex` varchar(6) NOT NULL DEFAULT '',
  `color_1_map_hex` varchar(6) NOT NULL DEFAULT '',
  `color_2_map_hex` varchar(6) NOT NULL DEFAULT '',
  `color_3_map_hex` varchar(6) NOT NULL DEFAULT '',
  `color_4_map_hex` varchar(6) NOT NULL DEFAULT '',
  `color_5_map_hex` varchar(6) NOT NULL DEFAULT '',
  `color_1_percent` double unsigned NOT NULL DEFAULT '0',
  `color_2_percent` double unsigned NOT NULL DEFAULT '0',
  `color_3_percent` double unsigned NOT NULL DEFAULT '0',
  `color_4_percent` double unsigned NOT NULL DEFAULT '0',
  `color_5_percent` double unsigned NOT NULL DEFAULT '0',
  `color_1_distance` double unsigned NOT NULL DEFAULT '0',
  `color_2_distance` double unsigned NOT NULL DEFAULT '0',
  `color_3_distance` double unsigned NOT NULL DEFAULT '0',
  `color_4_distance` double unsigned NOT NULL DEFAULT '0',
  `color_5_distance` double unsigned NOT NULL DEFAULT '0',
  `sequence` int(11) unsigned NOT NULL,
  PRIMARY KEY (`media_id`),
  KEY `index_on_timestamp` (`sequence`),
  KEY `index_on_map_hex` (`color_1_map_hex`,`color_2_map_hex`,`color_3_map_hex`,`color_4_map_hex`,`color_5_map_hex`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

第二个架构并不那么简单,但它确实避免了使用group,每个媒体只允许1行。但是,它似乎也有同样的问题,即找出map_hex值匹配的内容。以下是一个示例查询:

SELECT sql_no_cache media_id, 
(IF(color_1_percent = '61615a',color_1_percent,1)) * 
(IF(color_2_percent = '34362d',color_2_percent,1)) * 
(IF(color_3_percent = 'dbd5dd',color_3_percent,1)) as percentage, 

(IF(color_1_distance = '61615a',color_1_distance,1)) + 
(IF(color_2_distance = '34362d',color_2_distance,1)) + 
(IF(color_3_distance = 'dbd5dd',color_3_distance,1)) as distance, 

color_1_map_hex, color_2_map_hex, color_3_map_hex, color_4_map_hex, color_5_map_hex, 

(IF(color_1_map_hex = '61615a',1,1)) + 
(IF(color_2_map_hex = '34362d',1,1)) + 
(IF(color_3_map_hex = 'dbd5dd',1,1)) as matchCount 

FROM media_has_colors 
WHERE   color_1_map_hex IN ('61615a','34362d','dbd5dd') OR 
        color_2_map_hex IN ('61615a','34362d','dbd5dd') OR 
        color_3_map_hex IN ('61615a','34362d','dbd5dd') 
ORDER BY matchCount DESC, distance, percentage DESC 
LIMIT 100;

您可以看到计算百分比和距离时出现问题,因为实际的map_hex值可能不会出现在这些特定列中。

更新: 我不需要具体知道查询中匹配的颜色,但我需要按哪个匹配最高匹配。

所以我的问题是,如何修复架构或查询?如果没有,是否有更好的解决方案?

0 个答案:

没有答案