1. 程式人生 > >為快速高維OLAP實現殼片段shell-fragment的方法(具體實現)

為快速高維OLAP實現殼片段shell-fragment的方法(具體實現)

本文目錄結構

資料儲存

為方便程式的讀取,同時節約記憶體開支,我把儲存在csv檔案中的資料讀入資料庫,在資料庫中建立oriTable用來存放原始表格資料。

索引建立

原始索引

通過一遍掃描(按列掃描),為原始資料表中的部分欄位(根據資料特點和具體的需要進行選取)建立索引。並且在相同資料庫下為每一個欄位建立一張表,用來存放該欄位下全部資料的倒排索引表。

殼片段的完全資料立方體的倒排索引

對每一個片段(egA1,A2,A3),需要對它的每一個方體(eg A1,A2)的每一個單元(eg,1/0,0/0,1/1,1/0)計算倒排索引表,對每一個單元,記錄它關聯的TID列表。並存入資料庫。

在殼片段計算完成之後,處理點查詢和子立方體查詢。

對於點查詢

首先對查詢語句進行處理,劃分成殼片段的部分和單一維度的部分,對於“*”由於是不相關的,把它視為孤立的單一維度,並且不對它進行處理。

對於子立方體查詢

把?詢問的維度看作是單一維度,對於它的每一個值,分別與其他的各個例示的值組成一條點查詢。如果有兩個或者三個問號,則需要進行交叉。這個就把一個複雜問題分解成了許多個可以handle的小問題。
殼片段與完全立方體的區別

下面是一些技術細節(附程式碼)

1.我的專案目錄結構:
專案目錄結構
簡要介紹一下每一個類的功能。
其實我覺得我的命名很規範,算了,不介紹了。給你個眼神你自己體會。

DataToDB(將csv檔案中的原始資料 寫到資料庫中去)

表是我手動建立的,核心還是呼叫了DBU的插入函式。

package com.chang;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

public class DataToDB {
	public static ArrayList<String> readCsv(String filepath) {
		File csv = new File(filepath); // CSV檔案路徑
		csv.setReadable(true);// 設定可讀
		csv.setWritable(true);// 設定可寫
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(csv));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		String line = "";
		String everyLine = "";
		ArrayList<String> allString = new ArrayList<>();
		try {
			while ((line = br.readLine()) != null) // 讀取到的內容給line變數
			{
				everyLine = line;
				allString.add(everyLine);
			}
			System.out.println("csv表格中所有行數:" + allString.size());
		} catch (IOException e) {
			e.printStackTrace();
		}
		return allString;
	}
	//前提是先在資料庫中建立好了表。
	public static void main(String[] args) {
		System.out.println("hello");
		ArrayList<String> arrayList = new ArrayList<>();
		// .\代表當前路徑
		arrayList = readCsv("./resourse\\employees.csv");
		//獲取到列名陣列。
		String col_names = arrayList.remove(0);
		String[] col_names_array = col_names.split(",");
		System.out.println(Arrays.toString(col_names_array));
		int i=0;
		for (String str : arrayList) {
			// System.out.println(str);
			i++;
			String[] values_array =str.split(",");
			System.out.println(Arrays.toString(values_array));
			DBUtil.insert("ori_table", col_names_array, values_array);
			System.out.println(i);
		}
	}
}

效果如下圖:
資料庫的原始資料表

DBUtil.java (資料庫互動)

其中在建立表之前,加入了判斷,如果已經存在同名的表,那麼將同名的表刪除掉。在select函式取資料的時候,怎麼都取不出來,後來發現是因為數字作欄位名,需要數字兩邊加上``。還有一個獲取表的列名的函式,用的地方其實挺多,挺有用的。由於存放殼片段產生的索引的需要,我在DBUtil中加入了一個建表的函式,輸入是表名和欄位名的陣列,輸出當然是資料庫裡的一張表啦,不太好的是這個函式被我寫死了,因為是用來存長長的索引串的,所以一律採用longtext儲存。

package com.chang;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Properties;

import com.mysql.cj.jdbc.PreparedStatement;
import com.mysql.cj.jdbc.result.ResultSetMetaData;

public class DBUtil {

	private static String dbDriver = "com.mysql.cj.jdbc.Driver";
	private static String dbUrl;
	private static String dbUser;
	private static String dbPass;

	public static boolean config(String mysqlURL, String mysqlUserName, String mysqlPassword) {
		try {
			Class.forName(dbDriver);
		} catch (ClassNotFoundException e) {
			System.err.println(e);
			return false;
		}

		dbUrl = mysqlURL;
		dbUser = mysqlUserName;
		dbPass = mysqlPassword;
		System.out.println("URL:" + dbUrl);
		System.out.println("UserName:" + dbUser);
		System.out.println("Password:" + dbPass);
		try {
			Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPass);
			conn.close();
		} catch (SQLException e) {
			System.err.println(e);
			dbUrl = null;
			dbPass = null;
			dbUser = null;
			return false;
		}
		return true;
	}

	public static Connection getConn() {
		try {
			Class.forName(dbDriver);
		} catch (ClassNotFoundException e) {
			System.err.println(e);
			return null;
		}
		Connection conn;
		if (dbUrl == null || dbUser == null || dbPass == null) {
			Properties prop = new Properties();
			try {
				prop.load(DBUtil.class.getResourceAsStream("/application.properties"));
			} catch (IOException e) {
				System.err.println(e);
				return null;
			}
			dbUrl = prop.getProperty("mysqlURL");
			dbUser = prop.getProperty("mysqlUserName");
			dbPass = prop.getProperty("mysqlPassword");
		}
		try {
			conn = DriverManager.getConnection(dbUrl, dbUser, dbPass);
		} catch (SQLException e) {
			System.err.println(e);
			return null;
		}
		return conn;
	}

	public static void release(Connection conn, Statement st, ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
		if (st != null) {
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	/*
	 * @param tableName,the target parameters,the parameter values
	 * 
	 * @return flag(true->success)
	 */
	public static boolean insert(String table, String[] params, String[] params_value) {
		boolean flag = true;
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		String sql = "insert into " + table + " (";
		for (int i = 0; i < params.length - 1; i++) {
			sql += "`" + params[i] + "`" + ",";
		}
		sql += "`" + params[params.length - 1] + "`" + ") values (";
		for (int j = 0; j < params_value.length - 1; j++) {
			sql += "'" + params_value[j] + "' ,";
		}
		sql += "'" + params_value[params_value.length - 1] + "');";
		try {
			conn = getConn();

			try {
				st = (PreparedStatement) conn.prepareStatement(sql);
			} catch (SQLException e) {
				flag = false;
				e.printStackTrace();
			}
			try {
				st.executeUpdate();
			} catch (SQLException e) {
				flag = false;
				e.printStackTrace();
			}
		} finally {
			release(conn, st, rs);
		}
		return flag;
	}

	/*
	 * select {params} from table
	 */
	public static String[][] select(String table, String[] params) {
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		String[][] result = null;
		String sql = "select ";
		for (int i = 0; i < params.length - 1; i++) {
			sql +="`"+ params[i] +"`"+ ",";
		}
		sql +="`"+ params[params.length - 1] + "`"+" from " + table;
		try {
			conn = getConn();
			try {
				st = (PreparedStatement) conn.prepareStatement(sql);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				rs = st.executeQuery();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			java.sql.ResultSetMetaData mm = null;
			try {
				mm = rs.getMetaData();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			int columns = 0;
			try {
				columns = mm.getColumnCount();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			int rowCount = 0;
			try {
				rs.last();
				rowCount = rs.getRow();
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				rs.beforeFirst();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			int k = 0;
			try {
				result = new String[rowCount][columns];
				while (rs.next()) {
					for (int i = 1; i <= columns; i++) {
						try {
							result[k][i - 1] = rs.getString(i);
						} catch (SQLException e) {
							e.printStackTrace();
						}
					}
					k++;
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return result;

		} finally {
			release(conn, st, rs);
		}

	}

	/**
	 * 建立表
	 * 
	 * @param tabName
	 *            表名稱
	 * @param tab_fields
	 *            表字段
	 */
	public static void createTableOri(String tabName, String[] tab_fields) {
		// 首先要獲取連線,即連線到資料庫
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			conn = getConn();
			String sql = "create table " + tabName + "(id int auto_increment primary key not null";
			if (tab_fields != null && tab_fields.length > 0) {
				sql += ",";
				int length = tab_fields.length;
				for (int i = 0; i < length; i++) {
					// 新增欄位
					sql += tab_fields[i].trim() + " varchar(50)";
					// 防止最後一個,
					if (i < length - 1) {
						sql += ",";
					}
				}
			}
			// 拼湊完 建表語句 設定預設字符集
			sql += ")DEFAULT CHARSET=utf8;";
//			System.out.println("建表語句是:" + sql);
			ps = (PreparedStatement) conn.prepareStatement(sql);
			ps.executeUpdate(sql);
			ps.close();
			conn.close(); // 關閉資料庫連線
		} catch (SQLException e) {
			System.out.println("建表失敗" + e.getMessage());
		}
	}

	public static void createTable(String tabName, String[] tab_fields) {
		// 首先要獲取連線,即連線到資料庫
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			conn = getConn();
			String sql = "create table " + tabName + "(";
			if (tab_fields != null && tab_fields.length > 0) {
				int length = tab_fields.length;
				for (int i = 0; i < length; i++) {
					// 新增欄位
					sql += "`" + tab_fields[i].trim() + "`" + " longtext";
					// 防止最後一個,
					if (i < length - 1) {
						sql += ",";
					}
				}
			}
			// 拼湊完 建表語句 設定預設字符集
			sql += ");";
//			System.out.println("建表語句是:" + sql);
			ps = (PreparedStatement) conn.prepareStatement(sql);
			ps.executeUpdate(sql);
			ps.close();
			conn.close(); // 關閉資料庫連線
		} catch (SQLException e) {
			System.out.println("建表失敗" + e.getMessage());
		}
	}

	
            
           

相關推薦

快速高維OLAP實現片段shell-fragment方法初步設想

初步設想 把資料存入資料庫。額,怎麼也插不進去,最後發現,left這個欄位名不被接受,有可能是和mysql的關鍵字衝突了,所以不被允許,改了之後就可以了。 如何為每一個維集合也就是每一個片段計算立方體呢?根據每一個維的每一個值的倒排索引表唄。倒排索引表以字串的格式存在數組裡。物化

快速高維OLAP實現片段shell-fragment方法具體實現

本文目錄結構 資料儲存 索引建立 原始索引 殼片段的完全資料立方體的倒排索引 在殼片段計算完成之後,處理點查詢和子立方體查詢。 對於點查詢 對於子立方體查詢 下面是一些技術細節(附程式

如何快速通過url定位到controller中的方法採用AOP

aspect 攔截controller顯示指明 import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotat

Android Studio 快速實現上傳專案到Github詳細步驟

前言: 本文主要講解如何將Android Studio專案上傳至GitHub,在此之前,先介紹幾個概念。 Android Studio:是谷歌推出一個Android整合開發工具,基於IntelliJ IDEA,類似 Eclipse ADT,Android Studio 提供了整合的 Android 開發工具用

【面試題】實現一個棧,要求Push入棧,Pop出棧,Min返回最小值的操作的時間複雜度O1

問題描述:實現一個棧,要求Push(入棧),Pop(出棧),Min(返回最小值的操作)的時間複雜度為O(1)  分析問題:要記錄從當前棧頂到棧底元素的最小值,很容易想到用一個變數,每push一個元素更新一次變數的值。那麼問題來了,當執行pop操作時,上一次的最小值就找不到

[演算法入門]快速排序非遞迴方法Java實現,大家一起來找茬啊~

基礎 總結一下,快速排序的步驟: 1、找到一個key值(就是陣列第一個值),先從右到左找,找到一個比它小的值,記錄下標。 2、然後從左往右找,找到一個比它大的值,記錄下標。 3、交換找到的兩個數

騰訊面試題:模板實現一個棧,要求Push入棧,Pop出棧,Max返回最大值的操作的時間複雜度O(1)

解題思路:要用模板實現亂序入棧的陣列每次pop()出棧都能得到當前棧中Max的最大值,就必須在push()入棧時進行維護操作,使的每次入棧的元素都能夠找到合適的位置並push(),每次push()操作完成後棧中的元素都能夠按從棧頂到棧底從大到小排列即可。這就需要寫一個不同於常

Nginx實現七層的負載均衡LB Nginx

lb nginx Nginx實現七層的負載均衡調度到不同組後端服務器1. 動靜分離2. 網站進行分區=================================================================================拓撲結構

【LeetCode-面試算法經典-Java實現】【130-Surrounded Regions圍繞區域

pos apt pub iso all 左面 ons || title 【130-Surrounded Regions(圍繞區域)】 【LeetCode-面試算法經典-Java實現】【全部題目文件夾索引】 原題   Given a 2D b

【LeetCode-面試算法經典-Java實現】【054-Spiral Matrix螺旋矩陣

[] -a order detail tty util lis title comment 【054-Spiral Matrix(螺旋矩陣)】 【LeetCode-面試算法經典-Java實現】【全部題目文件夾索引】 原題   Given a

C語言實現單鏈表節點的刪除帶頭結點

data art pos grand urn ria tps move sni 我在之前一篇博客《C語言實現單鏈表節點的刪除(不帶頭結點)》中具體實現了怎樣在一個不帶頭結點的單鏈表的刪除一個節點,在這一篇博客中我改成了帶頭結點的單鏈表。代碼演示樣例上傳至 h

【LeetCode-面試算法經典-Java實現】【066-Plus One加一

ext javascrip ide new dig lis leetcode .net store 【066-Plus One(加一)】 【LeetCode-面試算法經典-Java實現】【全部題目文件夾索引】 原題   Given a no

【LeetCode-面試算法經典-Java實現】【139-Word Break單詞拆分

put art als min 全部 detail set 長度 trac 【139-Word Break(單詞拆分)】 【LeetCode-面試算法經典-Java實現】【全部題目文件夾索引】 原題   Given a string s a

C語言實現單鏈表的節點插入帶頭結點

alloc tails 函數 file ret con 實現 單獨 fun 我在之前一篇博客《C語言實現單鏈表(不帶頭結點)節點的插入》中具體實現了怎樣在一個不帶頭結點的單鏈表中進行節點的插入。可是在實際應用中,帶頭結點的鏈表更為經常使用。更為方便。今天我們

【LeetCode-面試算法經典-Java實現】【062-Unique Paths唯一路徑

ade ssi comment span there sdn href func 圖片 【062-Unique Paths(唯一路徑)】 【LeetCode-面試算法經典-Java實現】【全部題目文件夾索引】 原題   A robot is

ViewPager,實現真正的無限循環定時+手動

pre san fcm drawable size 消息 water selected nts 利用定時器,實現循環輪播,很簡單;只需在定時器的消息裏加如下代碼即可: int count = adapter.getCount(); if (count >

css實現垂直水平居中的方法個數不限

實現 容易 css3 pre height blog pad 絕對定位 fresh 方法一:使用絕對定位 大家都知道margin:0 auto;能夠實現水平居中,但卻不知道margin:0 auto;也是可以實現垂直居中的; 給居中元素添加如下樣式:

Shell編程轉—總結

bsp shel sed 正則表達式 grep 字符處理 進行 總結 正則 一、基礎正則表達式 1、正則表達式與通配符 正則表達式:用來在文件中匹配符合條件的字符串,正則是包含匹配,grep、awk、sed等命令支持正則表達式

c#實現圖片二值化例子黑白效果

rec con devel 圖片 round amp bsp 操作 spl C#將圖片2值化示例代碼,原圖及二值化後的圖片如下: 原圖: 二值化後的圖像: 實現代碼:using System; using System.Drawing; namespace BMP2G

WebAPI Ajax 跨域請求解決方法CORS實現

custom XML header 就會 情況 取數 -o cross serve 概述 ASP.NET Web API 的好用使用過的都知道,沒有復雜的配置文件,一個簡單的ApiController加上需要的Action就能工作。 但是在使用API的時候總會遇到跨